參考網站:
Docker官網文檔 https://docs.docker.com
中文翻譯 http://www.widuu.com/docker/
Docker Hub https://hub.docker.com/
Docker博客 https://blog.docker.com/
阿里雲Docker鏡像庫 https://dev.aliyun.com
一、Docker簡介
1.什麼是docker? Docker是一個開源的引擎,可以輕鬆的爲任何應用創建一個輕量級的、可移植的、自給自足的容器。開發者在筆記本上編譯測試通過的容器可以批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集羣和其他的基礎應用平臺。 官方的描述是:Build, Ship, and Run Any App, Anywhere 在任何地方部署,傳輸,運行任何應用 Docker類似虛擬機的概念,但是跟虛擬機比起來更靈活,速度更快,CPU/內存消耗更低,關鍵是更方便管理。與虛擬化技術的不同點在於下面幾點: 1)虛擬化技術依賴物理CPU和內存,是硬件級別的;而docker構建在操作系統上,利用操作系統的containerization技術,所以docker甚至可以在虛擬機上運行。 2)虛擬化系統一般都是指操作系統鏡像,比較複雜,稱爲“系統”;而docker開源而且輕量,稱爲“容器”,單個容器適合部署少量應用,比如部署一個redis、一個memcached 3)傳統的虛擬化技術使用快照來保存狀態;而docker在保存狀態上不僅更爲輕便和低成本,而且引入了類似源代碼管理機制,將容器的快照歷史版本一一記錄,切換成本很低 4)傳統的虛擬化技術在構建系統的時候較爲複雜,需要大量的人力;而docker可以通過Dockfile來構建整個容器,重啓和構建速度很快。更重要的是Dockfile可以手動編寫,這樣應用程序開發人員可以通過發佈Dockfile來指導系統環境和依賴,這樣對於持續交付十分有利 5)Dockerfile可以基於已經構建好的容器鏡像,創建新容器。Dockerfile可以通過社區分享和下載,有利於該技術的推廣
2.結構組成 底層由"核心系統kernel,文件系統等構成",上面是鏡像(p_w_picpath),分爲基礎鏡像(只讀)和普通鏡像,所有鏡像可以直接啓動生成一個實例(container),container就可以理解爲一個可以直接運行的虛擬機了。 container和p_w_picpath在Docker的世界裏,Image是指一個只讀的層(Layer),這裏的層是AUFS裏的概念,最直觀的方式就是看一下docker官方給出的圖 Docker使用了一種叫AUFS的文件系統,這種文件系統可以讓你一層一層地疊加修改你的文件,最底下的文件系統是隻讀的,如果需要修改文件,AUFS會增加一個可寫的層(Layer),這樣有很多好處,例如不同的Container可以共享底層的只讀文件系統(同一個Kernel),使得你可以跑N多個Container而不至於你的硬盤被擠爆了!這個只讀的層就是Image!而如你所看到的,一個可寫的層就是Container。 那Image和Container的區別是什麼?很簡單,他們的區別僅僅是一個是隻讀的層,一個是可寫的層,你可以使用docker commit 命令,將你的Container變成一個Image,也就是提交你所運行的Container的修改內容,變成一個新的只讀的Image,這非常類似於git commit命令。 Docker 由下面這些組成: 1) Docker 服務器守護程序(server daemon),用於管理所有的容器。 2) Docker 命令行客戶端,用於控制服務器守護程序。 3) Docker 鏡像:查找和瀏覽 docker 容器鏡像。
3.Docker特性 文件系統隔離:每個進程容器運行在完全獨立的根文件系統裏。 資源隔離:可以使用cgroup爲每個進程容器分配不同的系統資源,例如CPU和內存。 網絡隔離:每個進程容器運行在自己的網絡命名空間裏,擁有自己的虛擬接口和IP地址。 寫時複製:採用寫時複製方式創建根文件系統,這讓部署變得極其快捷,並且節省內存和硬盤空間。 日誌記錄:Docker將會收集和記錄每個進程容器的標準流(stdout/stderr/stdin),用於實時檢索或批量檢索。 變更管理:容器文件系統的變更可以提交到新的映像中,並可重複使用以創建更多的容器。無需使用模板或手動配置。 交互式Shell:Docker可以分配一個虛擬終端並關聯到任何容器的標準輸入上,例如運行一個一次性交互shell。
二、Docker的安裝使用
1.安裝環境
Docker 可以安裝在 Linux,Mac,Windows上,可以參考官方安裝文檔 https://docs.docker.com/engine/installation/linux/centos/。
環境要求必須是Centos6.5以上,X64位系統,內核版本至少3.10
默認目錄文件結構說明
/etc/sysconfig/docker 默認配置文件 /var/lib/docker/ Docker相關的本地資源 /var/lib/docker/container/ 存放容器信息 /var/lib/docker/graph/ 存放鏡像信息
2.兩種安裝方法,yum直接安裝和從 get.docker.com 調用腳本安裝
2.1 使用yum 安裝 # yum install docker # docker --version # 檢查是否安裝成功 2.2 使用官方提供的腳本安裝(首先確定你已經在"牆外") # curl -sSL https://get.docker.com/ | sh 17.04版本以後的安裝方法 # export CHANNEL=stable # curl -fsSL https://get.docker.com/ | sh -s -- --mirror Aliyun 啓動 # service docker start # chkconfig docker on # 開機啓動 下載最新的centos鏡像 # docker pull centos # docker p_w_picpaths # 查看所有鏡像 測試鏡像 # docker run -i -t centos /bin/bash # exit # 退出 注意:若有提示"Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning." 修改文件 “/etc/sysconfig/docker-storage”, 按照提示添加內容 “DOCKER_STORAGE_OPTIONS="--storage-opt dm.no_warn_on_loop_devices=true"” 然後重啓docker # service docker restart
3.常用命令
常用命令可分爲以下幾種 1.容器生命週期管理 # docker [run|start|stop|restart|kill|rm|pause|unpause] 2.容器操作運維 # docker [ps|inspect|top|attach|events|logs|wait|export|port] 3.容器rootfs命令 # docker [commit|cp|diff] 4.鏡像倉庫 # docker [login|pull|push|search] 5.本地鏡像管理 # docker [p_w_picpaths|rmi|tag|build|history|save|import] 6.其它命令 # docker [info|version]
3.1)鏡像相關操作命令: 創建鏡像的方法有三種 基於已有鏡像的容器創建 基於本地模板導入 基於Dockerfile文件創建 commit 基於已有鏡像的容器再生成一個新的鏡像 # docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] -m,--message="" 提交信息,爲鏡像描述內容 -a,--author="" 作者信息 -p,--pause=true 提交時暫停容器運行 My_Container:1 是提交的鏡像名稱和版本 # docker commit -m "Centos7 x64 First Image" -a "Loren" 33d619155d03 My_centos7:1 import 基於本地模板導入容器快照,將一個容器快照文件導入本地 # cat centos.tar | docker import - test/centos:v1.0 build 根據Dockerfile文件創建一個新的鏡像 # docker build [OPTIONS] PATH | URL | - -t 設定鏡像名稱及其標示號 -f,--file=Dockerfile 指定Dockerfile文件路徑 # docker build -t test:2 -f /opt/ search Image_name 在docker index中搜索p_w_picpath --automated=false -s N, --stars=0 指定評價爲N星級以上的鏡像 # docker search centos6 pull Image_name 從docker register server 中下拉p_w_picpath或者repository # docker pull centos # docker pull centos:centos6 # docker pull dl.dockerpool.com:5050/centos:6.8 指定網站下載 push 推送一個p_w_picpath或者repository到registry 上傳之前要把上傳的p_w_picpath的tag修改爲 hup用戶名/鏡像名字:tag 如 # docker tag centos6.8:v1 644597521/centos6.8:v1 p_w_picpaths 顯示本地的所有鏡像列表 rmi 刪除指定id的鏡像 tag 修改鏡像名 # docker tag test:1 My_p_w_picpath:v2 修改test標記好爲1的名稱爲My_p_w_picpath標記號爲v2 save 保存鏡像到本地文件 Usage: docker save [OPTIONS] IMAGE [IMAGE...] -o, --output="" # docker save -o centos_6.4.tar centos6.4:v1 # 導出本地的centos6.4:v1鏡像爲centos_6.4.tar文件 load 將本地文件導入到本地鏡像庫 Usage:docker load [OPTIONS] -i, --input="" # docker load < centos_6.4.tar # 將centos_6.4.tar文件導入到本地鏡像列表 inspect 顯示鏡像或容器的信息。返回的是JSON格式信息,若只要其中一項內容,可以使用-f指定
3.2)容器常用操作命令 run 運行一個新的container # Usage:docker run [OPTIONS] IMAGE [COMMAND] [ARG...] -a,--attack -i,--interactive=false 以交互模式運行容器,通常和-t搭配 -t,--tty=false 分配一個僞輸入終端 -d 後臺運行 -P 允許外部訪問容器所有開啓的端口 -p 端口映射 -p 80:80 --name 指定啓動後容器的名字 # docker run -i -t centos # docker run -i -t -d centos /bin/bash # docker run -i -t -d --name My_Container centos /bin/bash # docker run -i -t -d -p 80:80 --name My_Container centos /bin/bash -v,--volume=[] 創建數據卷 /mnt 在容器中創建一個數據卷 /webapp:/src/webapp 目錄掛載。將本地的webapp目錄掛載到容器的/src/webapp。容器和宿主機的掛載目錄都會同時變化 /test.txt:/tmp/text.txt 文件掛載。將本地的/test.txt文件掛載到容器的/tmp/text.txt(注意,只能修改容器掛載內的文件,否則不同步) # docker run -ti -v /da --name=dbdata centos 創建一個容器dbdata,並創建一個數據卷掛載容器dbdata的/da目錄 --volume-from 共享掛載數據卷 # # docker run -ti -v /mnt --name db centos 創建一個數據卷容器db,並創建一個數據卷掛載到容器db的/mnt目錄下 # docker run -ti --volume-from=db --name db1 centos # db1容器掛載db 容器中的數據卷 # docker run -ti --volume-from=db --name db2 centos # db2容器掛載db 容器中的數據卷 此時三個容器db,db1,db2都可以分享目錄/mnt --link 連接其他容器 --link NAME:Alias Name要建立連接的容器名,Alias連接的容器的別名 # docker run -ti -d -P --name web --link lamp:lamp centos6.4 /bin/bash 新建容器web和已經運行的容器lamp連接 ps 顯示容器的列表 -a 顯示所有信息 -q 只顯示ID # docker inspect 5d20c5528521 顯示容器的詳細信息 # docker ps -a -q ID # docker inspect -f "{{ .State.Pid }}" 5d20c5528521 顯示運行容器的PID stop|start|restart 停止|啓動|重啓容器 exec 進入容器(推薦使用) # docker exec [OPTIONS] CONTAINER COMMAND [ARG...] # docker exec -t -i 216c623071b3 /bin/bash attack CONTAINER_ID 進入容器 # docker attack 216c623071b3 使用 attach 命令有時候並不方便。當多個窗口同時 attach 到同一個容器的時候,所有窗口都會同步顯示。當某個窗口因命令阻塞時,其他窗口也無法執行操作了 nsenter # yum install util-linux # PID=$(docker inspect -f "{{ .State.Pid }}" 5d20c5528521) # nsenter --target $PID --mount --uts --ipc --net --pid # nsenter --target 10981 --mount --uts --ipc --net --pid -t, --target <pid> 要獲取名字空間的目標進程 -m, --mount[=<file>] enter mount namespace -u, --uts[=<file>] enter UTS namespace (hostname etc) -i, --ipc[=<file>] enter System V IPC namespace -n, --net[=<file>] enter network namespace -p, --pid[=<file>] enter pid namespace rm 刪除一個容器 -f, --force=true 強制刪除 -l, --link=false 刪除容器的連接,但保留容器 -v, --volumes=false 刪除容器掛載的數據卷 export 導出容器,導出一個已經創建的容器到一個文件,不管此時這個容器是否處於運行狀態 -o, --output="" # docker export 929bf12bc6ea > centos_6.4_php.tar
3.3)其它常用命令 docker -H 127.0.0.1:1234 -d & 修改服務端監聽本地的TCP連接1234端口 volume 管理docker的文件 login 登錄倉庫https://hub.docker.com/,登錄成功後信息保存文件在用戶家目錄/.docker/config.json 輸入用戶,密碼,郵件。 下載 .bashrc_docker,並將內容放到 .bashrc 中 # wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker; # echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc # source ~/.bashrc 這個文件中定義了很多方便使用 Docker 的命令,例如 docker-pid 可以獲取某個容器的 PID; 而 docker-enter 可以進入容器或直接在容器內執行命令
三、Dockerfile的使用
Dockerfile 一般分爲四部分: 基礎鏡像信息、維護者信息、鏡像操作指令、容器啓動執行指令 例子: # cat Dockerfile # Dockerfile 註釋 FROM centos6.8:1 指定基於的基礎鏡像,第一條必須爲FROM指令 MAINTAINER loren 維護者信息 LABEL Date='2016-06-06 10:11' RUN yum install -y ntpdate;yum install -y vim 鏡像的操作指令 CMD 容器啓動時執行的指令
指令: 1.FROM <p_w_picpath>:<tag> 告訴Docker使用哪個鏡像作爲基礎,第一條必須爲FROM指令,可以使用多個FROM指令(每個鏡像一次) 2.MAINTAINER <author name> 作者信息 3.RUN <Command>或 RUN ["executable","param1","param2"] 前者在shell終端運行命令,即 /bin/sh -c;後者使用exec執行,如 RUN ["/bin/bash", "-c", "echo hello"] 4.CMD 描述容器啓動後運行的服務命令,有三種格式 CMD ["executable", "param1", "param2"] 使用exec執行(推薦使用) CMD ["/bin/bash","-c","echo hello"] CMD command param1 param2 在/bin/sh 中執行,以“/bin/sh -c”方法執行。提供給需要交互的應用 CMD echo "hello world" CMD ["param1", "param2"] 提供給ENTRYPOINT 的默認參數 CMD ["-D","--help"] 指定啓動容器時執行的命令,每個Dockerfile 只能有一條 CMD 命令。如果多個則只會執行最後一條 若果用戶啓動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令 5.EXPOSE 向外部開放端口 EXPOSE <port> [<port>...] EXPOSE 22 80 8443 6.ENV 指定一個環境變量,會被後續RUN指令使用,並在容器運行時保持 EVN <key> <value> ENG PG_MAJOR 9.3.4 RUN ..... ENV PATH /usr/local/postgres-$PG-MAJOR/bin/:$PATH 7.ADD 將複製指定的<src> 到容器的 <dest>,其中<src>可以是Dockerfile所在目錄的一個相對路徑(文件或目錄),也可以是一個URL,還可以是一個tar文件(會自動解壓爲目錄) ADD <src> <dest> 8.COPY 複製本地的主機的 <src> 爲容器中的 <dest>。若目標路徑不存在時,會自動創建 COPY <src> <dest> 9.ENTRYPOINT 容器啓動後執行的命令,並且不可被 docker run 提供的參數覆蓋。 每個Dockerfile中只能有一個 ENTRYPOINT,當指定多個 ENTRYPOINT時,只有最後一個生效 ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2 (shell中執行) 一般是配合CMD使用,CMD提供默認參數,如: ENTRYPOINT ["/usr/sbin/sshd"] CMD ["-D"] 10.VOLUME 創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等 VOLUME ["/data"] 11.USER 指定容器運行時的用戶名或UID,後續的 RUN也會使用指定用戶。使用gosu代替sudo獲取管理員權限 USER daemon 12.WORKDIR 指定配置工作目錄 WORKDIR /path/to/workdir WORKDIR /a WORKDIR b 13.ONBUILD 配置當所創建的鏡像作爲其他新創建鏡像的基礎鏡像時,所執行的操作指令 ONBUILD [INSTRUCTION] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
Dockerfile 實例
下面是創建sshd服務的Dockerfile文件實例
# cat /opt/docker_builder/sshd/Dockerfile FROM centos6.8:1 # 指定基礎鏡像 MAINTAINER Loren <[email protected]> LABEL Date='2016-06-14 16:39' # Install sshd service 安裝sshd服務 RUN yum install -y openssh-server # Add authorized_keys -> /root/.ssh/authorized_keys 和本機建立互信 RUN mkdir -p /root/.ssh;chmod 700 /root/.ssh ADD authorized_keys /root/.ssh/authorized_keys # Password for ROOT 設置容器的root密碼 RUN echo '1' | passwd root --stdin # script for sshd 提供開機自啓動腳本 ADD ssh.sh /root/ssh.sh RUN chmod 755 /root/ssh.sh # Read from socket failed: Connection reset by peer 當ssh連接容器時的錯誤提示解決方法 RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key;ssh-keygen -t dsa -f /etc/ssh/ssh_host_rsa_key # OPEN Port 22 開發ssh服務容器的端口 EXPOSE 22 # Command 開機啓動腳本 CMD ["/root/ssh.sh"] # cat ssh.sh #!/bin/bash /usr/sbin/sshd -D 通過Dockerfile 文件創建鏡像,並指定Dockerfile文件路徑 # docker build -t sshd:t1 /opt/docker_builder/sshd/ # docker run -d -p 2020:22 sshd:t1 啓動sshd服務容器,本機端口2020映射到容器22端口 此時就可以通過本機的ssh連接到sshd服務容器 # ssh IP 2020
ssh連接失敗提示: "Read from socket failed: Connection reset by peer" 解決方法: #ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key;ssh-keygen -t dsa -f /etc/ssh/ssh_host_rsa_key
使用Dockerfile 安裝nginx實例
# cat Dockerfile FROM sshd/centos6.8:t1 MAINTAINER Loren <[email protected]> [2016-06-15 14:48] # Install nginx RUN yum install -y nginx RUN echo "daemon off;" >> /etc/nginx/nginx.conf RUN echo "Hello Container Nginx!" >> /usr/share/nginx/html/index.html EXPOSE 80 CMD ["/usr/sbin/nginx"] # docker build -t nginx/centos6.8:t1 . 創建nginx容器 # docker run -d -p 8000:80 nginx/centos6.8:t1 啓動nginx容器
使用Dockerfile安裝Tomcat實例
目錄結構: /opt/tomcat/ ├── Dockerfile └── packages ├── apache-tomcat-6.0.41.zip └── jdk-6u45-linux-x64-rpm.bin # cat Dockerfile FROM sshd:centos6.8 MAINTAINER Loren <[email protected]> [2016-06-17 16:13] ENV JAVA_HOME /usr/java/jdk1.6.0_45 ENV JRE_HOME $JAVA_HOME/jre ENV PATH $PATH:$JAVA_HOME/bin # Base programesoft RUN yum install -y unzip vim wget # For jdk RUN mkdir -p /soft ADD ./packages/jdk-6u45-linux-x64-rpm.bin /soft RUN cd /soft;chmod 755 jdk-6u45-linux-x64-rpm.bin;./jdk-6u45-linux-x64-rpm.bin # For tomcat RUN mkdir -p /data COPY ./packages/apache-tomcat-6.0.41.zip /soft RUN unzip -o /soft/apache-tomcat-6.0.41.zip -d /data/ RUN chmod 777 /data/apache-tomcat-6.0.41/bin/*.sh EXPOSE 8080 CMD ["/data/apache-tomcat-6.0.41/bin/catalina.sh", "run"] # docker build -t tomcat/centos6.8:v1 /opt/tomcat/ 創建tomcat/centos6.8:v1容器 # docker run -d -P tomcat/centos6.8:v1 啓動tomcat/centos6.8:v1 容器
使用Dockerfile安裝Tomcat實例
目錄結構: /opt/httpd/ ├── Dockerfile ├── run_httpd.sh └── sample └── index.html # cat Dockerfile # For apache install FROM centos6.8:1 MAINTAINER Loren <[email protected]> [2016-06-15 11:08] # Installed RUN yum install -y httpd RUN sed -i 's/#\(ServerName\)\ www.example.com:80/\1\ localhost:80/g' /etc/httpd/conf/httpd.conf # Add html COPY sample/index.html /var/www/html # Simple startup scipt to avoid some issues observed with container restart ADD run_httpd.sh /run_httpd.sh RUN chmod 755 /run_httpd.sh # OPEN port 80 EXPOSE 80 CMD ["/run_httpd.sh"] ENV HOME /root WORKDIR /root # cat run_httpd.sh #!/bin/bash # FileName: run_httpd.sh # Author: Loren # Date: 2016-06-15 11:22 # Info: For start httpd with container restart #exec /usr/sbin/apachectl -D FOREGROUND /usr/sbin/httpd -k start # cat sample/index.html <!DOCTYPE html> <html> <body> <h1>Hello, Container!</h1> </body> </html> # docker build -t httpd/centos6.8:v1 /opt/httpd/ 創建httpd容器 # docker run -d -P httpd/centos6.8:v1 啓動httpd容器