docker入門篇
- 2019 年 10 月 5 日
- 筆記
基礎知識不回顧了,直接上。
docker的安裝與啟動
yum remove docker -y
yum install docker-io -y # 需要先配置好epel源
/etc/init.d/docker start
chkconfig docker on
獲取鏡像
docker pull centos # 從docker倉庫下載一個鏡像例如:docker pull centos:6.7
docker p_w_picpaths #列出本地已存在的鏡像
docker p_w_picpaths centos # 查看指定的鏡像
運行
# docker run centos /bin/echo'Hello world'
# docker run -i -t centos:6.7/bin/bash
-i表示輸入終端保持打開狀態
-t表示開一個偽終端,並綁定到標準輸入上
-c限制運行的某個容器的CPU配額【最大默認是1024】
–cpuset-cpus= 設置可以綁定使用幾個CPU,具體可以看help
-d 表示後台運行容器,只輸出容器的ID到屏幕
-P表示–publish-all=false Publish all exposed ports to random ports
–hostname=docker1.demo.com 表示修改容器的hsotname
–name=lnmp1 表示給啟動的容器命名,不用隨機名稱
–dns=xx.xx.xx.xx 自定義DNS服務器地址【不指定該參數的話,就是要外部主機的/etc/resolv.conf來配置容器】
–add-host "www.demo.com:192.168.2.2" 在容器的/etc/hosts添加一條指定的DNS解析記錄
–expose80 –expose 8080 # 暴露端口在外部Expose a port or a range of ports
–memory1G 限制容器最大使用的內存
*centos後面如果不指定版本,則默認選擇latest版本
輸入exit或者Ctrl+d退出
# docker run -ti –name test3–hostname=docker1.demo.com –dns=192.168.2.2 –dns=8.8.8.8 lanmp:v1 /bin/bash # 複雜的寫法
# docker run -d ubuntu:14.04/bin/sh -c "while true; do echo hello world; sleep 1; done" 以後台進程模式運行
# docker logs 後面跟容器的NAMES
當利用 docker run 來創建容器時,Docker 在後台運行的標準操作包括:
檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
利用鏡像創建並啟動一個容器
分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
從地址池配置一個 ip 地址給容器
執行用戶指定的應用程序
執行完畢後容器被終止
# docker ps 查看在運行中的docker實例進程
# docker logs insane_babbage 查看容器中的標準輸出
# docker stop insane_babbage 停止某個容器
# docker ps可以看到剛才啟動的那個centos容器沒有了
# docker ps -a 可以看到所有的容器(包括已停止的)
# docker start insane_babbage # 如果加-i參數可以進入交互式的容器
# docker version 查看docker客戶端版本和進程的版本信息
ubuntu容器安裝軟件:
默認安裝好的ubuntu docker是沒有vim和ping這些命令的。
進入容器後,執行
# apt-get update
# apt-get install vim -y
然後vi /etc/apt/sources.list 添加阿里雲的源地址。
# apt-get install inetutils-ping-y
# ping www.qq.com 即可
查看幫助信息
# docker 只輸入docker指令,系統會自動列出全部可用的命令列表
# docker p_w_picpaths –help
創建鏡像方法1:修改鏡像
# docker run -i -t centos:6.7/bin/bash 記下容器的ID,例如:e2d6c890682f
在容器中添加LAMP環境
# yum install httpd mysql mysql-server php php-mysql -y
# exit 退出容器
# docker commit -m "Add LAMPenv" -a "CentOS_LAMP" e2d6c890682f 6.7lamp 提交更新後的副本
-m message
-a author
# docker p_w_picpaths 可以看到已經生成了一個鏡像
# docker run -i -t 6.7lamp/bin/bash 用剛才創建的鏡像啟動容器
另外,可以使用docker commit -m 'my nignx' e2d6c890682fdemo/my_nginx:v1 這種創建帶明顯標誌的鏡像。
啟動的話使用docker run -d -p 88:80 –name "ningx_1" demo/my_nginx:v1 即可。
方法2、dockerfile創建基於centos6.7的nginx的容器
mkdir /opt/docker-file
cd /opt/docker-file
mkdir nginx && cd nginx
vi Dockerfile 內容如下:
# This is My First Dockerfile
# Verson 1.0
# Author: Lee
FROM centos:6.7
MAINTAINER Lee
ADD pcre-8.36.tar.gz/usr/local/src <— 1、需要事先把這個tar.gz包拷貝到當前目錄下,即和Dockerfile在同一個目錄下
ADD nginx-1.11.5.tar.gz/usr/local/src <—2、如果是個壓縮包,拷到容器後會自動解壓的,無需我們解壓操作
RUN rm -fr /etc/yum.repos.d/*
RUN wget -O/etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
RUN wget -O/etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
RUN yum clean all
RUN yum install -y wget gcc gcc-c++ make openssl-devel
RUN useradd -s /sbin/nologin -Mwww
WORKDIR/usr/local/src/nginx-1.11.5
RUN ./configure–prefix=/usr/local/nginx –user=www –group=www –with-http_ssl_module –with-http_stub_status–with-pcre=/usr/local/src/pcre-8.36 && make && make install
RUN echo 'daemon off;' >>/usr/local/nginx/conf/nginx.conf
RUN sed 's@#user nobody;@user www;@g' nginx.conf
ENV PATH/usr/local/nginx/sbin:$PATH
EXPOSE 80
CMD ["nginx"]
docker build -t dockfile:v2 . 這樣就可以創建鏡像了
啟動剛才創建的nginx docker容器的話,使用docker run -d -p 8888:80 dockfile:v2即可。
參數說明:
指令:
FROM <p_w_picpath>[:tag>] 或者FROM <p_w_picpath>@<digest> # 必須是第一個非注釋的行,用於指定所用到的基礎鏡像
MAINTAINER <author's detail>
COPY ["<src>", …"<dest>"] 複製本地主機的目錄到容器里的指定目錄
<src>是要複製的源文件或目錄,支持通配符
<dest>目標路徑,正在創建的鏡像文件的文件系統路徑(建議使用絕對路徑)
說明:所有新複製生成的目錄文件的UID和GID都是0
例如: COPY /home/template/server.xml/etc/tomcat/server.xml
COPY *.conf /etc/httpd/conf.d/
注意:src 必須是build上下文的路徑,即不能使用類似../../conf/*.conf,但是還是可以使用絕對路徑例如/home/conf.d/*.conf ;src如果是目錄的話,遞歸複製會自動進行;如果有多個src,包括在src上使用了通配符,此時dest必須是目錄,而且必須得以/結尾。
dest如果事先不存在,它會被自動創建,包括其父目錄。
ADD 類似COPY指令,額外還支持複製tar格式的文件及URL路徑。【ADD比COPY用得更常見些】
例如:ADD haproxy.cfg /etc/haproxy/haproxy.cfg
ADDlogstash_*.cnf /etc/logstash/
ADD http://www.demo.com/download/nginx.conf/etc/nginx/ 【URL格式指定的源文件,下載完成後其目標文件權限為600】
如果src是一個宿主機上的tar文件,則它將被解壓展開成要給目錄(類似tar xf命令,如果通過URL下載的是個tar文件,則不會被自動展開)
ENV 定義環境變量,此些變量可以被當前dockerfile文件中的其它指令所調用,調用格式為$variable_name或${variable_name}
語法:
ENV<key> <value> 一次定義一個變量
或者 ENV <key>=<value>… 一次可以定義多個變量,如果value中有空白字符,要是進行轉義
如: ENV myName="Tom Lee" myDog='wang cai'
說明:ENV定義的環境變量在鏡像運行的整個過程中一直存在,因此可以使用docker inspect查看,甚至可以用docker run –env=xxx 來修改其值
USER 指定運行容器時,或者運行RUN CMD ENTRYPOINT指令指定的程序時使用的用戶名或者UID
格式: USER <UID>|<Username>
WORKDIR 為後續的RUN、CMD、ENTRYPOINT、COPY、ADD指令配置工作目錄
如:
WORKDIR/a
WORKDIRb
WORKDIRc
RUNpwd
則最終路徑為 /a/b/c
另外, WORKDIR還可以調用由ENV定義的環境變量的值,如: WORKDIR $STATEPATH
ENTRYPOINT
VOLUME 在目標鏡像文件中創建一個掛載點,用來掛載主機上的卷或其他容器的卷。一般用來存放數據庫和需要保持的數據等。
VOLUME<mountpoint>
例如: VOLUME ["/data/mysql","/data/Images"]
注意:如果mountpoint路徑下事先有文件存在,則在掛載完成後,會同時顯示當前的文件和掛載前的文件(AUFS的疊加原理)。
RUN
每個RUN都會另起一層,所以建議將多個命令放到一行,減少AUFS的層數。
格式:
RUN <command> # 會啟動一個shell解釋器
或RUN ["<executeable>","<param1>","<parma2>",…] # 不會啟動shell解釋器
例如:
RUNyum install iproute nginx && yum clean all
RUN['/bin/bash','-c','yum','install','httpd']
CMD 設定在docker run時默認執行的命令
格式: CMD <command> 或CMD ["<executeable>","<param1>","<parma2>"]
或CMD["<param1>","<param2>",…] 為ENTRYPOINT指令指定的程序提供默認參數。
如果dockerfile中存在多個CMD指令,則只有最後一個生效。
例如:
CMD["/usr/sbin/httpd","-c","/etc/httpd/conf/httpd.conf"]
ENTRYPOINT 類似CMD指令,但其不會被docker run的命令行參數指定的指令所覆蓋。且這些命令行參數會被當中參數送給ENTRYPOINT指令指定的程序
如果運行docker run時使用了–entrypoint選項,則此選項的參數可以覆蓋掉dockerfile默認的entrypoint參數。
格式:
ENTRYPOUNT<command>
ENTRYPOUNT["executeable","<param1>","<param2>",…]
例如:
注意:
如果CMD和ENTRYPOINT都存在的話,則CMD的指令會被附加到ENTRYPOINT後,變成ENTRYPOINT的參數。
EXPOSE 用於為容器指定要暴露的端口
格式:EXPOSE<port>[/protocol>][<port>[/<protocol>]]…
如:
EXPOSE11211/tcp 11211/udp
ONBUILD 配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令
例如: ONBUILD ADD my.cnf /etc/mysql/my.cnf
注意:ONBUILD不能自我嵌套,且不會觸發。
導出鏡像
# docker save -o/root/centos_lamp_v3.tar centos/lamp:v3
導入鏡像
# docker load–input /root/centos_lamp_v3.tar
或者docker load </root/centos_lamp_v3.tar
# 這將導入鏡像以及其相關的元數據信息(包括標籤等)
移除鏡像
# docker rmicentos/lamp:v3
注意:在刪除鏡像之前要先用dockerrm 刪掉依賴於這個鏡像的所有容器。
想要刪除untagged p_w_picpaths,也就是那些id為<None>的p_w_picpath的話可以用
# docker rmi$(docker p_w_picpaths | grep "^<none>" | awk "{print $2}")
要刪除全部p_w_picpath的話
# docker rmi$(docker p_w_picpaths -q)
刪除已停止的容器
# docker rm -f$(docker ps -a -q)
移除容器
# docker rm5d6da6754d01
停止所有的container,這樣才能夠刪除其中的p_w_picpaths:
# docker stop$(docker ps -a -q)
如果想要刪除所有container的話再加一個指令:
# docker rm$(docker ps -a -q)
從本地文件系統導入一個鏡像
要從本地文件系統導入一個鏡像,可以使用 openvz(容器虛擬化的先鋒技術)的模板來創建: openvz 的
模板下載地址為 templates 。
比如,先下載了一個 ubuntu-14.04 的鏡像,之後使用以下命令導入:
catubuntu-14.04-x86_64-minimal.tar.gz |docker import – ubuntu:14.04
上傳鏡像
docker pushouruser/sinatra
進入容器
在使用 -d 參數時,容器啟動後會進入後台。某些時候需要進入容器進行操作,有很多種方法,包括使用docker attach 命令或 nsenter 工具等
# docker attach 容器NAME
或者docker exec-ti 容器ID /bin/bash
但是使用 attach 命令有時候並不方便。當多個窗口同時 attach 到同一個容器的時候,所有窗口都會同步顯示。當某個窗口因命令阻塞時,其他窗口也無法執行操作了。使用attach進到容器後要退出的話,只能關閉xshell了,使用exit會導致整個容器的退出。
nsenter 這個進入容器的命令也很好用(如果沒有的話需要安裝util-linux-ng)。
方法:
dockerinspect –format"“.`State`.`Pid`" 容器NAME或者容器ID號 # 結果會輸出一個容器的pid號
nsenter –target 容器的pid號 –mount –uts –ipc –net–pid
上面2條命令可以做成腳本,in.sh 內容如下:
#!/bin/bash
CNAME=$1
CPID=$(dockerinspect –format"“.`State`.`Pid`" $CNAME)
nsenter–target $CPID –mount –uts –ipc –net –pid
sh in.sh 容器的NAME或者ID號,即可進入容器。
導出容器快照到本地文件
# docker ps -a
# docker export 容器名稱 > ubuntu.tar
導入容器快照為鏡像
# cat ubuntu2.tar |docker import – test/ubuntu:v1
# docker p_w_picpaths
自己基於centos構建nginx容器:
首先啟動一個centos容器,然後在裏面安裝nginx(我這裡是yum安裝的nginx)。
修改nginx的配置文件,加上daemon off; 參數。
然後繼續。下面有2種方法啟動容器時候讓它自動啟動nginx
方法1:
dockercommit -m 'nginx_v1' eb919426f773 6.7_nginx_v1
dockerrun -d -p 888:88 –name 'nginx_v1' 6.7_nginx_v1 /usr/sbin/nginx
這樣就可以了。
方法2:
修改容器的/etc/bashrc 加上/usr/sbin/nginx -c/etc/nginx/nginx.conf
dockerrun -d -p 888:88 –name 'nginx_v1' 6.7_nginx_v1 /bin/bash
docker私有倉庫的搭建
【作為倉庫的虛擬機IP為:192.168.2.11】:
# 必須先啟動docker registry【centos6上是這樣的。在centos7上則變成了一個守護進程,需要用systemctl來啟動】
# docker pullregistry
# docker run -d-p 5000:5000 -v /opt/data/registry:/tmp/registry registry
# docker ps 記下容器NAME為kickass_wright
# 默認情況下,倉庫會被創建在容器的 /tmp/registry 下。可以通過 -v 參數來將鏡像文件存放在本地的指定路徑。
# docker p_w_picpaths 列出當前的鏡像
# docker tag88e44a5cbd17 192.168.2.11:5000/centos/lamp
格式:dockertag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
# docker p_w_picpaths
Docker從1.3.X之後,與docker registry交互默認使用的是https,然而此處搭建的私有倉庫只提供http服務,所以當與私有倉庫交互時就會報上面的錯誤。為了解決這個問題需要在啟動docker server時增加啟動參數為默認使用http訪問。
修改docker配置文件將代碼加到/etc/sysconfig/docker的other_args="–insecure-registry192.168.2.11:5000"裏面。
# docker stopkickass_wright 停掉registry容器
#/etc/init.d/docker restart 重啟docker
# docker startkickass_wright 啟動registry容器
# docker push192.168.2.11:5000/centos/lamp 將本地鏡像推送到本機上的私有服務器上
這樣本地鏡像就是上次到私有docker 倉庫了。
我們可以在其他節點測試能否下載這個鏡像。如果沒問題的話,就可以在本機上刪除原有的docker鏡像,如下:
# docker rmi 192.168.2.11:5000/centos/lamp
在Node2節點(192.168.2.12)測試:
# yum installdocker-io -y
修改docker配置文件將代碼加到/etc/sysconfig/docker的other_args="–insecure-registry192.168.2.11:5000"裏面。
#/etc/init.d/docker restart 重啟docker
# docker pull192.168.2.11:5000/centos/lamp 從192.168.2.11的私有倉庫下載鏡像
# docker p_w_picpaths 可以看到已經下載好了相關的鏡像
docker的監控命令:
docker ps [-a]
docker p_w_picpaths
docker stats Container_name # 實時查看某個容器的負載情況
docker top Container_name # 實時查看某個容器的狀態統計(類似top命令)
dockerinspect # 查看容器或鏡像的底層信息
例如:docker inspect -f'“.`Config`.`Hostname`' d413082da04e 類似ansible的 ansible -m setup的輸出格式
此外,還有谷歌提供的CAdvisor web界面的監控工具;Scout工具,Data Dog工具,等。具體可參考: http://dockone.io/article/397
數據卷:
數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:
- 數據卷可以在容器之間共享和重用
- 對數據卷的修改會立馬生效
- 對數據卷的更新,不會影響鏡像
- 卷會一直存在,直到沒有容器使用
*數據卷的使用,類似於 Linux 下對目錄或文件進行 mount
下面創建一個web 容器,並加載一個數據卷到容器的/webapp 目錄:
# docker run -d-P –name web -v /webapp training/webapp python app.py
# 這樣只寫名容器中的目錄不寫宿主機的目錄的話,實際上是在宿主機的/var/lib/docker/volumes/xxxx/目錄下的。不常用這種寫法。
-v 標記來創建一個數據卷並掛載到容器里。在一次 run 中多次使用可以掛載多個數據卷
*注意:也可以在 Dockerfile 中使用 VOLUME 來添加一個或者多個新的卷到由該鏡像創建的任意容器。
掛載一個主機目錄src/webapp作為容器的數據卷:
# docker run -d-P –name web2 -v /src/webapp:/opt/webapp training/webapp python app.py
# 格式:-v 本地路徑:容器路徑
* 上面的命令加載主機的 /src/webapp 目錄到容器的 /opt/webapp 目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。
* 本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你創建它。
* 注意:Dockerfile 中不支持這種用法,這是因為 Dockerfile 是為了移植和分享用的。然而,不同操作系統的路徑格式不一樣,所以目前還不能支持。
Docker 掛載數據卷的默認權限是讀寫,用戶也可以通過:ro 指定為只讀。
# sudo docker run-d -P –name web -v /src/webapp:/opt/webapp:ro training/webapppython app.py
-v 標記也可以從主機掛載單個文件到容器中
# docker run –rm-it -v ~/.bash_history:/.bash_history ubuntu /bin/bash 【不同shell版本有所不同】
*注意:如果直接掛載一個文件,很多文件編輯工具,包括 vi 或者 sed –in-place ,可能會造成文件inode 的改變,從 Docker 1.1 .0起,這會導致報錯誤信息。所以最簡單的辦法就直接掛載文件的父目錄。
數據卷容器:
如果你有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。
數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
首先,創建一個數據卷容器dbdata,並在其中創建一個數據卷掛載到/dbdata:
# docker run -i-t -v /dbdata –name dbdata ubuntu:12.04/bin/bash
再啟動2個容器測試
# docker run -i-t –volumes-from dbdata –name db1 ubuntu:12.04/bin/bash
# docker run -i-t –volumes-from dbdata –name db2 ubuntu:12.04/bin/bash
# 注意:–volumes-from後面跟的是具備容器卷的那個容器名
此時容器db1和db2都掛載同一個數據卷到相同的/dbdata目錄。三個容器任何一方在該目錄下的寫入,其他容器都可以看到。[即便原來的那個數據卷容器已經停止了]
查看數據卷實際的存放路徑:
docker inspect -f“.`Volumes` 數據卷容器的NAME或ID
map[/dbdata:/var/lib/docker/volumes/7c12ca73fe29f884ea5bee12c54da521c7450705264f76fe8629877302cd48aa/_data]
可以看到這個容器卷是把文件寫入到/var/lib/docker/volumes下面的某個很長的字符串的目錄下的_data/裏面
容器和宿主機間文件拷貝的解決方法:
docker ps 獲取目標容器的ID或者容器的名稱 # 我這裡的是容器ID為52261df2fab6
docker inspect-f'“.`Id`' 容器的ID # 獲取容器的ID全名稱
得到一串類似52261df2fab612b24b3502c4ad98c22aff70ce9fa641c5c9f735ac2415e92da3
cp /root/test.log/var/lib/docker/devicemapper/mnt/52261d…xxx/rootfs/root/ # 這樣就把宿主機的test.log拷貝到容器的/root/目錄下了。
# 說明:上面的這個方法在CentOS6.7通過yum安裝的docker-io測試通過。我另一台測試機安裝的是docker-engine,則根本沒有/rootfs/這個目錄。
還可以使用多個–volumes-from 參數來從多個容器掛載多個數據卷。
# docker run -i-t -v /dbdata –name dbdata ubuntu:12.04/bin/bash
# docker run -i-t -v /webdata –name webdata ubuntu:12.04/bin/bash
# docker run -i-t –volumes-from dbdata –name db1 –volumes-fromwebdata –name web1 ubuntu:12.04 /bin/bash
此外,也可以從其他已經掛載了數據卷的容器來掛載數據卷。
*注意:
使用 –volumes-from 參數所掛載數據卷的容器自己並不需要保持在運行狀態。
如果刪除了掛載的容器(包括 dbdata、db1 和 db2),數據卷並不會被自動刪除。
如果要刪除一個數據卷,必須在刪除最後一個還掛載着它的容器時使用 "docker rm -v 容器名" 命令來指定同時刪除關聯的容器。這可以讓用戶在容器之間升級和移動數據卷。另外,如果啟動時候加了–rm參數,則容器關閉時自動刪除容器並刪除卷。
利用數據卷容器來備份數據
# docker run -i-t -v /dbdata –name dbdata ubuntu:12.04 /bin/bash
# cp /etc/issue/etc/group /dbdata
另外啟動一個容器,對剛才的容器數據進行備份操作
# docker run –volumes-fromdbdata -v $(pwd):/backup –name bk1 ubuntu:12.04 tar czf/backup/backup.tar.gz /dbdata
# 格式:dockerrun –volumes-from要備份的容器名-v 宿主機目錄:/backup ubuntu:12.04 tar czf /backup/xx.tar.gz 需要備份的容器的卷名稱
*容器啟動後,使用了 tar 命令來將 dbdata 卷備份為容器下的/backup/backup.tar.gz,這個容器執行完就自動退出了(因為沒有-ti 或-d參數),
*同時在宿主機下當前目錄下生成backup.tar.gz壓縮文件(參數-v $(pwd):/backup就是這個作用).
利用數據卷容器來恢複數據
如果要恢複數據到一個容器,首先創建一個帶有數據卷的容器 dbdata2。
# docker run -it-v /dbdata –name dbdata2 ubuntu:12.04 /bin/bash
隨便在/dbdata裏面複製些文件,以便後面恢複數據時用於識別。
然後創建另一個容器,掛載 dbdata2 的容器,並使用tar解壓備份文件到掛載的容器卷中。
#docker run –volumes-from dbdata2 -v $(pwd):/backup ubuntu:12.04 tar xf/backup/backup.tar.gz
