docker --- 初識

Docker簡介

     Docker是一個開源的引擎,能夠輕鬆的爲任何應用建立一個輕量級的、可移植的、自給自足的容器。開發者在筆記本上編譯測試經過的容器能夠批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集羣和其餘的基礎應用平臺。mysql

Docker用於場景

    web應用的自動化打包和發佈;nginx

    自動化測試和持續集成、發佈;web

    在服務型環境中部署和調整數據庫或其餘的後臺應用;sql

    從頭編譯或者擴展示有的OpenShift或Cloud Foundry平臺來搭建本身的PaaS環境。docker

安裝docker


    # yum install docker-io
    # systemctl start docker.service
    # systemctl enable docker.service
    # ifconfigshell

    宿主機出現 docker0 的虛擬網絡接口。

    docker 代理網絡設置
    # vim /etc/sysconfig/docker數據庫

HTTPS_PROXY=http://proxy.sinaabc.com:3128
HTTP_PROXY=http://proxy.sinaabc.com:3128

 # docker version     //查看docker的版本號,包括客戶端、服務端、依賴的Go等apache

   # docker info          //查看系統(docker)層面信息,包括管理的images, containers數等ubuntu


鏡像獲取使用


    鏡像能夠看做是包含有某些軟件的容器系統,好比ubuntu就是一個官方的基礎鏡像,不少鏡像都是基於這個鏡像「衍生」,該鏡像包含基本的ubuntu系統。再好比,hipache是一個官方的鏡像容器,運行後能夠支持http和websocket的代理服務,而這個鏡像自己又基於ubuntu。 

    搜索鏡像
    # docker search ubuntu12.10 

    下載鏡像
    # docker pull ubuntu12.10x64

    查看鏡像  
    # docker images              列出images 
    # docker images -a          列出全部的images(包含歷史) 
    # docker images --tree    顯示鏡像的全部層(layer) 
    # docker rmi  <image ID> 刪除一個或多個image 

    建立容器
    # docker run chug/ubuntu12.10x64  /bin/echo hello world
    hello worldvim

    建立運行不進入交互

    # docker run -itd  <image>  /bin/bash

    查看容器
    docker ps :列出當前全部正在運行的容器 
    docker ps -l :只顯示最新建立的容器,包括非運行的。
    docker ps -a :顯示全部容器。 默認只顯示運行容器。 
    docker ps -q :列出最近一次運行的container I D 

    再次啓動容器 
    docker start/stop/restart <container>  開啓/中止/重啓container
    docker start [container_id]                  再次運行某個container (包括歷史container)
    docker attach [container_id]               鏈接一個正在運行的container實例(即實例必須爲start狀態,能夠多個窗口同時attach 一個container實例)
    docker start -i <container>                  啓動一個container並進入交互模式(至關於先start,在attach) 

    進入容器 (進入前首先要啓動容器)
    docker exec -it 19ee6bc10189 /bin/bash   

    映射 HOST 端口到容器
    方便外部訪問容器內服務,host_port 能夠省略,省略表示把 container_port 映射到一個動態端口。
    docker run -i -t -p <host_port:container_port>  
    docker run -i -t -d -p 1200:11211  niexiaohu/centos-memcached

    刪除容器 
    docker rm <container...>                刪除一個或多個container
    docker rm `docker ps -a -q`           刪除全部的container
    docker ps -a -q | xargs docker rm  同上, 刪除全部的container 

    檢查運行中的鏡像
    docker inspect container_id

    發佈docker鏡像
    docker push docker.sinaabc.com/centos6

   保存對容器的修改
    docker commit [container_id] chug/nginx

    經過容器生成新的鏡像

    使用docker commit <container-id> <image-name> 命令能夠把一個正在運行的容器變成一個新的鏡像, repo:tag可選。

# docker commit d0fd23b8d3ac chug/ubuntu12.10x64_2
daa11948e23d970c18ad89c9e5d8972157fb6f0733f4742db04219b9bb6d063b
# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
chug/ubuntu12.10x64_2   latest              daa11948e23d        6 seconds ago       270.3 MB
chug/ubuntu12.10x64     latest              0b96c14dafcd        4 months ago        270.3 MB

持久化

       持久化容器 
        export命令用於持久化容器 
        docker export <container_id> > /tmp/export.tar


       持久化鏡像 
        Save命令用於持久化鏡像 
        docker save image_id > /tmp/save.tar 

       導入持久化container 
        # cat /tmp/export.tar | docker import - export:latest

        導入持久化image 
        # docker load < /tmp/save.tar

        對image打tag
        # docker tag daa11948e23d load:tag

其它操做

 

  docker logs $CONTAINER_ID                     查看docker實例運行日誌,確保正常運行
        docker inspect <image|container>              查看image或container的底層信息 

        docker build <path>                                    尋找path路徑下名爲的Dockerfile的配置文件,使用此配置生成新的image
        docker build -t repo[:tag]                             能夠指定repo和可選的tag
        docker build - < <dockerfile>                       使用指定的dockerfile配置文件,docker以stdin方式獲取內容,使用此配置生成新的image
        docker port <container> <container port>   查看本地哪一個端口映射到container的指定端口,其實用docker ps 也能夠看到

       docker文件存放目錄 
        Docker實際上把全部東西都放到 /var/lib/docker路徑下了。 
        # ls -F
        containers/  devicemapper/  execdriver/  graph/  init/  linkgraph.db  repositories-devicemapper  volumes/
        containers目錄固然就是存放容器(container)了,graph目錄存放鏡像,文件層(file system layer)存放在graph/imageid/layer路徑下,這樣咱們就能夠看看文件層裏到底有哪些東西,利用這種層級結構能夠    清楚的看到文件層是如何一層一層疊加起來的。

       查看root密碼 
        docker容器啓動時的root用戶的密碼是隨機分配的。因此,經過這種方式就能夠獲得容器的root用戶的密碼了。 
        docker logs 5817938c3f6e 2>&1 | grep 'User: ' | tail -n1

 

關於 Dockerfile

               Dockerfile 是一個鏡像的表示用來描述構建鏡像的步驟,Docker能夠從文本Dockerfile讀取指令做爲構建步驟並自動生成最終鏡像

 

  1.使用Dockerfile

     從源碼構建一個鏡像, 先建立一個名爲Dockerfile的描述文件在存儲庫的根目錄。 這個文件將描述鏡像構建步驟。
     調用Docker構建,源碼的路徑做爲構建參數,點表示當前目錄下,(例如,):
     $ sudo docker build .

     指定一個存儲庫和標籤 -t shykes/myapp .

     $ sudo docker build -t shykes/myapp .

 

  2.格式

  INSTRUCTION arguments (指令 參數 )

     指令是不區分大小寫的,建議指令都大寫,更容易區別於參數, 第一個指令必須「FROM」  以指定構建的基礎鏡像。

 以 '#'  開始做爲一個註釋。如:

# Comment
RUN echo 'we are running some # of cool things'

3. 指令

     在Dockerfile中使用指令集構建鏡像.
     基本經常使用的指令是:  FROMMAINTAINERRUNENTRYPOINTUSERESPOSEADD
 3.1 FROM

   語法:  FROM <image>   或  FROM <image>:<tag>

   Dockerfile第一個指令必須是 FROM,FROM 能夠出現屢次在單個Dockerfile爲了建立多個鏡像,FROM 後面爲基礎鏡像, 如:

FROM ubuntu
3.2 MAINTAINER

   語法: MAINTAINER <name>

 MAINTAINER命令用來指定維護者的信息說明:

MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>
3.3 RUN

   RUN命令會在上面FROM指定的鏡像裏執行任何命令,而後提交(commit)結果,生成新的圖層,提交的鏡像會在後面繼續用到。

   RUN兩種格式:



一、RUN <command> # 運行一個shell命令
RUN apt-get install -y openssh-server
3.3 RUN

   RUN命令會在上面FROM指定的鏡像裏執行任何命令,而後提交(commit)結果,生成新的圖層,提交的鏡像會在後面繼續用到。

   RUN兩種格式:



一、RUN <command> # 運行一個shell命令
RUN apt-get install -y openssh-server
二、exec 執行方式
語法:RUN ["executable", "param1", "param2" ... ]
RUN ["/bin/bash", "-c", "echo hello"] 
3.4 CMD

  CMD主要用於容器啓動時執行啓動服務的命令。Dockerfile 只能有一個CMD,若是有多個CMD則最後的CMD生效。

  CMD有三種方式:

  一、CMD ["executable","param1","param2"] (使用 exec 執行,推薦方式)

CMD ["/bin/bash", "-c", "echo hello"]

 二、 CMD ["param1","param2"]    (給 ENTRYPOINT 提供參數 ) 如:

FROM ubuntu
CMD ["-D","--help"]

 三、 CMD command param1 param2  ( 以」/bin/sh -c」方法執行命令) 如:

CMD echo "This is a test." | wc -
3.5 EXPOSE
    EXPOSE 命令能夠設置一個運行的鏡像中暴露在的外端口
語法:EXPOSE <port> [<port>...]

    如:Nginx使用80端口,把這個端口暴露在外,這樣容器外能夠看到這個端口並與其通訊。

EXPOSE 80
3.6 ENV

  ENV指令設置環境變量值

 語法: ENV <key> <value>
ENV LANG en_US.UTF-8
ENV APP_DIR /app
3.7 ADD

   複製新文件,並將它們添加到容器的文件系統路徑

   語法: ADD <src> <dest> 

ADD ./start.sh  /root/start.sh

<src> 是相對被構建的源目錄的相對路徑,能夠是文件或目錄的路徑,也能夠是一個遠程的文件url

<dest> 是container中的絕對路徑.

COPY  做用相似於ADD

語法: COPY <src> <dest> 。

複製本地主機的 <src> (爲Dockerfile所在目錄的相對路徑)到容器中的 <dest> 。

當使用本地目錄爲源目錄時,推薦使用 COPY 。

3.8 ENTRYPOINT

   意思是進入點,容器啓動時執行命令,一個Dockerfile中只能有一條ENTRYPOINT命令,若是多條則只執行最後一條ENTRYPOINT.

    ENTRYPOINT、CMD,通常二者能夠配合使用,CMD提供默認參數,好比:

 ENTRYPOINT ["/usr/sbin/sshd"]
  CMD ["-D"]
ENTRYPOINT 和 CMD的不一樣點在於執行docker run時參數傳遞方式,CMD指定的命令能夠被docker run傳遞的命令覆蓋:

一、CMD 指令:

CMD ["echo"]

運行 :

# docker run container_name echo foo

結果打印出: foo

二、ENTRYPOINT指令:

ENTRYPOINT ["echo"]

運行 :

# docker run container_name echo foo

結果打印出:echo foo

3.9 VOLUME

 建立一個能夠從本地主機或其餘容器掛載的掛載點,通常用來存放數據庫或須要保存的數據

VOLUME ["/data"]
3.10 USER

    指定使用哪一個用戶或uid運行鏡像

USER daemon
3.11 WORKDIR

 配置RUNCMDENTRYPOINT 命令設置當前工做路徑

WORKDIR /path/to/workdir

  語法:  ONBUILD [INSTRUCTION] 

ONBUILD ADD .  /app

   ONBUILD 在生成當前docker鏡像的時候不生效,在子鏡像生效;ONBUILD 在產品發佈時起着很是重要的做用。

   如:

   A鏡像中有ONBUILD指令,在構建A鏡像時ONBUILD指令不執行;B鏡像FROM A ,在構建B鏡像時 ONBUILD 指令開始執行;

 

4. Dockerfile Examples

1.官方實例:

'#' 爲註釋符,這裏Dockerfile構建4個鏡像,寫好Dockerfile文件後就能夠在該目錄下運行 docker build . 命令了(能夠用 -t 參數指定tag)

# Nginx
#
# VERSION 0.0.1

FROM      ubuntu
MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>

# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

RUN apt-get install -y inotify-tools nginx apache2 openssh-server
# Firefox over VNC
#
# VERSION 0.3

FROM ubuntu
# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get install -y x11vnc xvfb firefox
RUN mkdir /.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'

EXPOSE 5900
CMD    ["x11vnc", "-forever", "-usepw", "-create"]
# Multiple images example
#
# VERSION 0.1

FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f

FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4

# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.

 
示例2: 建立 一個運行ssh server鏡像
FROM centos6
# build ssh
MAINTAINER niexiaohu niexiaohu@yolo24.com
RUN echo "root:123456" | chpasswd
RUN yum install openssh-server
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ENTRYPOINT ["/usr/sbin/sshd"]
CMD ["-D"]
# CMD /usr/sbin/sshd -D 
EXPOSE 22

容器內啓動多個服務程序

     在一個 container中部署兩個以上服務程序的狀況和需求上,由於Dockerfile只容許執行一個CMD,這種狀況下須要藉助supervisor進程監控管理程序來啓動和管理container 內的多個程序。

一、建立Dockerfile:

FROM centos:centos6  

MAINTAINER xxx xxxx  "xxxx@hotmail.com"  

RUN rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm  
RUN yum install -y openssh-server sudo mysql-server mysql supervisor  
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config   

RUN useradd admin  
RUN echo "admin:admin" | chpasswd  
RUN echo "admin   ALL=(ALL)       ALL" >> /etc/sudoers  

RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key  
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key  
RUN mkdir /var/run/sshd  

RUN /etc/init.d/mysqld start &&\  
mysql -e "grant all privileges on *.* to 'root'@'%' identified by 'letmein';"&&\  
mysql -e "grant all privileges on *.* to 'root'@'localhost' identified by 'letmein';"&&\  
mysql -u root -pletmein -e "show databases;"  

RUN mkdir -p /var/log/supervisor  
COPY supervisord.conf /etc/supervisord.conf  

EXPOSE 22 3306  
CMD ["/usr/bin/supervisord"]

二、在Dockerfile所在目錄下建立supervisord.conf文件

[supervisord]  
nodaemon=true  

[program:sshd]  
command=/usr/sbin/sshd -D  

[program:mysqld]  
command=/usr/bin/mysqld_safe

3.在Dockerfile 當前目錄執行命令生成image.

# sudo docker build -t myserver .

完整部署 Web 應用

一、建立maven-demo和maven-repo目錄用做docker volume,這樣Maven建立的項目會持久化在maven-demo目錄下,maven的local repository持久話在maven-repo目錄下。
$ mkdir maven-demo maven-repo

二、運行maven docker新建一個Maven項目
$ docker run -it --rm --name maven-demo -v "$PWD"/maven-demo:/usr/src/maven-demo -v "$PWD"/maven-repo/:/root/.m2/repository -w /usr/src/maven-demo maven:3 mvn -B archetype:generate -DgroupId=com.aliyun.demo -DartifactId=hello-world -DarchetypeArtifactId=maven-archetype-webapp

運行成功後,能夠看到項目目錄結構以下:
hello-world
    |---pom.xml
    |---src
        |---main
            |---resource
            |---webapp
                |---WEB-INF
                |   |---web.xml
                |---index.jsp

三、構建Maven項目
$ docker run -it --rm --name maven-demo -v "$PWD"/maven-demo/:/usr/src/maven-demo -v "$PWD"/maven-repo/:/root/.m2/repository -w /usr/src/maven-demo/hello-world maven mvn package
構建成功後,hello-world目錄下多了一個target目錄,包含hello-world.war文件。

四、Docker鏡像打包:使用Docker運行Java Web應用,推薦基於Tomcat的Docker容器來打包、運行您的Java應用,選擇Tomcat的Docker基礎鏡像上構建應用鏡像。

Dockerfile以下所示:

FROM tomcat:8
ADD maven-demo/hello-world/target/hello-world.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]

五、打包鏡像
$ docker build -t docker.sinaabc.com/maven-demo-hello-world .

六、上傳到registry

$ docker push docker.sinaabc.com/maven-demo-hello-world

七、另一臺機器上獲取鏡像

$ docker pull docker.sinaabc.com/maven-demo-hello-world

八、運行Docker鏡像
$ docker run -d -p 8080:8080 docker.sinaabc.com/maven-demo-hello-world

打開瀏覽器訪問 http://hostip:8080/hello-world/ 將會看到 Hello World! 的輸出,表示編譯的hello-world war 包已經成功使用 Docker 運行起來了。

數據容器

FROM tomcat:8
ADD your.war /usr/local/tomcat/webapps/

使用這樣的Dockerfile構建出數據容器,並將它的volume與Tomcat容器共享。

$ docker build -t app-image . $ docker create -d -v /usr/local/tomcat/webapps/ --name app app-image true $ docker run -d --volumes-from app tomcat:8 

因爲系統必定會把共享volume的容器調度運行在同一臺宿主機上,這樣能夠保證正確運行。然而,因爲共享volume的容器只能被調度到同一臺宿主機上,這樣會限制系統的可伸縮性。

相關文章
相關標籤/搜索