經常使用Dockerbuild命令

基於Dockerfile構建鏡像

1. Dockerfile:source code for building Docker file

  • Docker能夠經過從Dockerfile文件中讀取指令自動構建鏡像
  • Dockerfile是一個文本文檔,它包含用戶能夠在命令行上調用的全部命令來組裝映像
  • 使用Docker build命令,用戶能夠經過逐條執行幾條命令自動建立鏡像

2. Dockerfile語法格式:

  • 首行必須是以#開頭的行
  • 不區分大小寫,但約定俗成的慣例都是使用所有大寫。
  • Docker按順序在Dockerfile中運行指令
  • 第一個指令必須是「FROM」,以便指定要從其中構建的基本映像

3. 環境變量(使用ENV語句聲明)也能夠在某些指令中使用,做爲由Dockerfile解釋的變量。

  • 在Dockerfile中,環境變量能夠是$variable_name或${variable_name}
    • ${variable_name}語法還支持一些標準bash修飾符
    • ${variable:-word}表示,若是設置了變量,那麼結果將是該值。若是變量未設置,則結果爲word。
    • ${variable:+word}表示若是設置了變量,那麼結果將是word,不然結果將是空字符串。

4. .dockerignore文件

  • 在工做目錄中如有子目錄,而子目錄中有些文件不想引用,就能夠用.dockerignore來隱藏文件。
  • .dockerignore文件內指明不引用的文件。

5. FROM

  • 用來指定基礎鏡像,若指定的鏡像不存在,會先到Docker Hub中下載
  • 語法:
    • FROM <image> [AS <name>] #[AS <name>]:別名
    • FROM <image>[:<tag>] [AS <name>] #tag:標籤
    • FROM <image> [@<digest>] [AS <name>] #digest:哈希碼

6. docker build命令

  • Build an image from a Dockerfile
  • Options
    • -t, --tag list Name and optionally a tag in the 'name:tag' format
    • -m, --memory bytes Memory limit
    • -c, --cpu-shares int CPU shares (relative weight)

7. LABEL

  • 添加鏡像文件的元數據,可出現屢次,強烈建議只使用一條,由於一條指令會添加一個層,層數越多,運行效率越低。
  • 語法格式:
    • LABEL <key>=<value> <key>=<value> <key>=<value>... #可指定多個LABEL
    • LABEL <key> <value> #只可指定一個LABEL,第一個空格後的內容都會被看成value

示例php

只修改一個鏡像的FROM、LABELhtml

  1. 建立工做目錄image
[root@docker ~]# mkdir image
[root@docker ~]# cd image
  1. 編輯Dockerfile文件,添加如下內容:
[root@docker image]# vim Dockerfile
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"
  1. 製做鏡像:
[root@docker image]# docker build .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM alpine
 ---> 3fd9065eaf02
Step 2/2 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Running in e1ce9acfc453
Removing intermediate container e1ce9acfc453
 ---> 1deb17a1af32
Successfully built 1deb17a1af32
  1. 查看:REPOSITORY和TAG都爲空的即爲新建立的鏡像文件
[root@docker image]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              1deb17a1af32        5 minutes ago       4.15MB
nginx               latest              cd5239a0906a        3 weeks ago         109MB
busybox             latest              8c811b4aec35        5 weeks ago         1.15MB
httpd               2.4                 fb2f3851a971        8 weeks ago         178MB
alpine              latest              3fd9065eaf02        5 months ago        4.15MB
  • 建立docker鏡像時,可以使用-t後跟 'name:tag' 指定TAG
  • 也可用以下命令添加標籤:
[root@docker image]# docker image tag 1deb17a1af32 alpine:lxk
[root@docker image]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
alpine                      lxk                 1deb17a1af32        5 minutes ago       4.41MB

8. COPY

  • 用於從Docker宿主機複製文件至建立的新映像文件
  • 語法:
    • COPY <src> ... <dest>
    • COPY ["<src>",... "<dest>"]
      • <src>:要複製的源文件或目錄,支持使用通配符
      • <dest>:目標路徑,即正在建立的image的文件系統路徑;建議爲<dest>使用絕對路徑,不然,COPY指定則以WORKDIR爲其起始路徑
      • 注意:在路徑中有空白字符時,一般使用第二種格式
  • 文件複製準則:
    • <src>必須是build上下文中的路徑,不能是其父目錄中的文件
    • 若是<src>是目錄,則其內部文件或子目錄會被遞歸複製,但<src>目錄自身不會被複制
    • 若是指定了多個<src>,或在<src>中使用了通配符,則<dest>必須是一個目錄,且必須以/結尾
    • 若是<dest>事先不存在,它將會被自動建立,這包括其父目錄路徑

示例:複製單個文件node

  1. 在image目錄下爲index.html添加內容:
[root@docker image]#  echo '<h1>hello,docker!</h1>' > index.html
  1. 編輯Dockerfile文件,添加語句:
[root@docker image]# vim Dockerfile 
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

COPY index.html /var/www/html/
  1. 用alpine啓動一個容器,查看是否有/var/www/html目錄
[root@docker image]# docker run -it --name a1 alpine
/ # ps aux 
PID   USER     TIME   COMMAND
    1 root       0:00 /bin/sh
    7 root       0:00 ps aux
/ # ls /var/www/html
ls: /var/www/html: No such file or directory
  1. 製做鏡像
[root@docker image]# docker build -t cpindex:latest .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM alpine
 ---> 3fd9065eaf02
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Running in 9d96e0655a82
Removing intermediate container 9d96e0655a82
 ---> 56049399eb78
Step 3/3 : COPY index.html /var/www/html/
 ---> bace8e55c97b
Successfully built bace8e55c97b
Successfully tagged cpindex:latest
  1. 查看製做的鏡像:
[root@docker image]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cpindex             latest              bace8e55c97b        52 seconds ago      4.15MB
  1. 以製做的鏡像啓動一個容器,並查看文件是否存在
[root@docker image]# docker run --name copyfile -it --rm cpindex:latest
/ # ls /var/www/html
index.html
/ # cat /var/www/html/index.html
<h1>hello,docker!</h1>

示例:複製目錄下的多個文件至目錄nginx

  1. 複製一個目錄至/root/image下
[root@docker image]# cp -r /etc/default/ ./ 
[root@docker image]# ls
default  Dockerfile  index.html
[root@docker image]# ls default/
grub  kibana  nss  useradd
  1. 修改Dockerfile文件爲如下內容:
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

COPY default /tmp/
  1. 製做鏡像:
[root@docker image]# docker build -t cpdir:latest ./
Sending build context to Docker daemon  9.216kB
Step 1/3 : FROM alpine
 ---> 3fd9065eaf02
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/3 : COPY default /tmp/
 ---> 18cacf50aef9
Successfully built 18cacf50aef9
Successfully tagged cpdir:latest
  1. 查看並驗證:
[root@docker image]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cpdir               latest              18cacf50aef9        24 seconds ago      4.15MB

[root@docker image]# docker run --name cpdir -it --rm cpdir:latest
WARNING: IPv4 forwarding is disabled. Networking will not work.
/ # ls /tmp
grub     kibana   nss      useradd

示例:使用數組格式建立配置文件web

  1. 修改配置文件以下:
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

COPY ["default","/tmp/default"]
  1. 建立鏡像並驗證
[root@docker image]# docker build -t cp:latest ./
Sending build context to Docker daemon  9.216kB
Step 1/3 : FROM alpine
 ---> 3fd9065eaf02
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/3 : COPY ["default","/tmp/default"]
 ---> bf0799319943
Successfully built bf0799319943
Successfully tagged cp:latest
[root@docker image]# docker run --name cp -it --rm cp:latest
/ # cd /tmp
/tmp # ls
default
/tmp # cd default/
/tmp/default # ls
grub     kibana   nss      useradd
/tmp/default # exit

9. ADD

  • ADD相似於COPY指令,ADD支持tar文件和URL路徑
  • Syntax
    • ADD <src>...<dest>
    • ADD ["<src>"..."<dest>"]
  • 操做準則:
    • 同COPY指令
    • 若是<src>爲URL且<dest>不以/結尾,則<src>指定的文件將被下載並直接被建立爲<dest>;若是<dest>以/結尾,則文件名URL指定的文件將被直接下載並保存爲<dest>/<filename>
    • 若是<src>是一個本地系統上的壓縮格式的tar文件,它將被展開爲一個目錄,其行爲相似於「tar -x」命令;然而,經過URL獲取到的tar文件將不會自動展開;
    • 若是<src>有多個,或其間接或直接使用了通配符,則<dest>必須是一個以/結尾的目錄路徑;若是<dest>不以/結尾,則其被視做一個普通文件,<src>的內容將被直接寫入到<dest>

示例:下載一個文件至鏡像文件redis

  1. 在工做目錄下編寫Dockerfile文件(使用URL時,用ftp協議失敗)
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

COPY ["default","/tmp/default"]

ADD https://mirrors.aliyun.com/centos/7.5.1804/os/x86_64/Packages/zsh-5.0.2-28.el7.x86_64.rpm /tmp/
  1. 建立鏡像文件
[root@docker image]# docker build -t zsh:latest ./
Sending build context to Docker daemon  9.216kB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/4 : COPY ["default","/tmp/default"]
 ---> Using cache
 ---> bf0799319943
Step 4/4 : ADD https://mirrors.aliyun.com/centos/7.5.1804/os/x86_64/Packages/zsh-5.0.2-28.el7.x86_64.rpm /tmp/
Downloading [==================================================>]  2.494MB/2.494MB

 ---> 538ab9c6983e
Successfully built 538ab9c6983e
Successfully tagged zsh:latest
  1. 建立容器並查看
[root@docker image]# docker run -it --name zsh --rm zsh:latest
/ # cd /tmp
/tmp # ls
default                      zsh-5.0.2-28.el7.x86_64.rpm

示例:ADD一個壓縮包至鏡像文件docker

  1. 複製壓縮包至工做目錄,並在工做目錄編輯Dockerfile文件
[root@docker image]# cp /root/wordpress-4.8.1-zh_CN.tar.gz ./
[root@docker image]# vim Dockerfile 
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

ADD wordpress-4.8.1-zh_CN.tar.gz /tmp/
  1. 製做鏡像文件
[root@docker image]# docker build -t wordpress:latest ./
Sending build context to Docker daemon  8.652MB
Step 1/3 : FROM alpine
 ---> 3fd9065eaf02
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/3 : ADD wordpress-4.8.1-zh_CN.tar.gz /tmp/
 ---> 58c32caba31e
Successfully built 58c32caba31e
Successfully tagged wordpress:latest
  1. 建立容器並查看
[root@docker image]# docker run --name a1 -it --rm wordpress:latest
/ # ls /tmp/wordpress/
index.php             wp-admin              wp-content            wp-load.php           wp-signup.php
license.txt           wp-blog-header.php    wp-cron.php           wp-login.php          wp-trackback.php
readme.html           wp-comments-post.php  wp-includes           wp-mail.php           xmlrpc.php
wp-activate.php       wp-config-sample.php  wp-links-opml.php     wp-settings.php
/ # exit

10. WORKDIR

  • 用於爲Dockerfile中全部的RUN、CMD、ENTRYPOINT、COPY和ADD指定設定工做目錄
  • Syntax
    • WORKDIR <dirpath>
      • 在Dockerfile文件中,WORKDIR指令可出現屢次,其路徑也能夠爲相對路徑,不過,其是相對此前一個WORKDIR指令指定的路徑
      • 另外,WORKDIR也可調用由ENV指定定義的變量
    • 例如:
      • WORKDIR /var/log
      • WORKDIR $STATEPATH

示例shell

  1. 在工做目錄下編輯Dockerfile文件:
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

WORKDIR /tmp
ADD wordpress-4.8.1-zh_CN.tar.gz src
  1. 建立鏡像:
[root@docker image]# docker build -t wordpress:v0.1 ./
Sending build context to Docker daemon  8.652MB
Step 1/4 : FROM alpine
 ---> 3fd9065eaf02
Step 2/4 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/4 : WORKDIR /tmp
Removing intermediate container 08bef4630472
 ---> 54f97eda6b49
Step 4/4 : ADD wordpress-4.8.1-zh_CN.tar.gz src
 ---> 0811aff4fa7d
Successfully built 0811aff4fa7d
Successfully tagged wordpress:v0.1
  1. 建立容器後,默認工做路徑就是WORKDIR所指的目錄/tmp
[root@docker image]# docker run --name a1 -it --rm wordpress:v0.1
/tmp # ls
src
/tmp # ls src/
wordpress
/tmp # ls src/wordpress/
index.php             wp-admin              wp-content            wp-load.php           wp-signup.php
license.txt           wp-blog-header.php    wp-cron.php           wp-login.php          wp-trackback.php
readme.html           wp-comments-post.php  wp-includes           wp-mail.php           xmlrpc.php
wp-activate.php       wp-config-sample.php  wp-links-opml.php     wp-settings.php
/tmp # exit

11. VOLUME

  • 用於在image中建立一個掛載點目錄,以掛載Docker host上的卷或其它容器上的卷
  • Syntax
    • VOLUME <mountpoint>
    • VOLUME ["<mountpoint>"]
  • 若是掛載點目錄路徑下此前有文件存在,docker run命令會把原文件隱藏.
  • 若是此前掛載點不存在,docker 會自動建立該目錄.
  • 掛載點下文件變化均可以在宿主機查看
    • 查看方法:
      • docker volume ls #查看宿主機全部掛載的目錄
      • docker inspect -f {{.Mounts}} a1 #經過查看指定容器信息查看掛載點路徑

示例數據庫

  1. 在須要掛載的目錄下提供文件
[root@docker image]# echo "hello,test dockerfile" > /var/www/html/index.html
  1. 在工做目錄下編輯Dockerfile文件
#Test Image Build
FROM alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

#WORKDIR /tmp
#ADD wordpress-4.8.1-zh_CN.tar.gz src/

VOLUME /var/www/html
  1. 建立鏡像文件
[root@docker image]# docker build -t file:v0.1 ./
Sending build context to Docker daemon  8.651MB
Step 1/3 : FROM alpine
 ---> 3fd9065eaf02
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56049399eb78
Step 3/3 : VOLUME /var/www/html
 ---> [Warning] IPv4 forwarding is disabled. Networking will not work.
 ---> Running in da84d9f4ca1e
Removing intermediate container da84d9f4ca1e
 ---> b26c2d7ea64c
Successfully built b26c2d7ea64c
Successfully tagged file:v0.1
  1. 建立容器:
[root@docker image]# docker run --name a1 -it --rm file
/ # cd /var/www/html/
/var/www/html # echo abc > index.html
/var/www/html # cat index.html
abc
  1. 查看宿主機上的文件:
[root@docker ~]# docker volume ls       #查看本機全部容器掛載的目錄
DRIVER              VOLUME NAME
local               6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735
[root@docker ~]# docker inspect -f {{.Mounts}} a1       #查看a1容器的掛載文件路徑
[{volume 6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735 /var/lib/docker/volumes/6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735/_data /var/www/html local  true }]
[root@docker ~]# cd /var/lib/docker/volumes/6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735/_data/
[root@docker _data]# ls
index.html
[root@docker _data]# cat index.html 
abc         #該內容與容器中index.html內容同樣

12. EXPOSE

  • 用於爲容器打開指定要監聽的端口以實現與外部通訊
  • 實質是經過iptables添加DNAT規則,把外網主機訪問宿主機的請求轉發至指定容器.
  • 須要宿主機開啓核心轉發功能.
  • 可經過iptables -t nat -nvL查看添加的規則.
  • 經過Dockerfile製做鏡像時若不用EXPOSE指定要暴露的端口,可用如下兩種方法暴露端口:
    • 容器運行後,自行添加DNAT規則實現端口暴露.
    • docker run時使用-p選項指定暴露的端口.
    • docker run時使用-P選項暴露全部容器內監聽的端口.
  • docker run時,使用-p選項指定的優先級要高於Dockerfile製做鏡像時指定要暴露的端口.
  • Syntax
    • EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]
      • <protocol>用於指定傳輸層協議,可爲tcp或udp兩者之一,默認爲TCP協議
  • EXPOSE指令可一次指定多個端口,例如
    • EXPOSE 11211/udp 11211/tcp

不用EXPOSE時,宿主機內容器若要被外網主機訪問的狀況vim

  1. 下載redis:4-alpine
[root@docker ~]# docker pull redis:4-alpine
4-alpine: Pulling from library/redis
ff3a5c916c92: Pull complete 
5fbab8756652: Pull complete 
ff7d4663b06c: Pull complete 
0b5cf71258c2: Pull complete 
54bbb9bad8ba: Pull complete 
8fe9a341d124: Pull complete 
Digest: sha256:686ab026fae07b3b99a8e74210c361714a80311ecc55f23b349ae930ed2f5a95
Status: Downloaded newer image for redis:4-alpine
[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               4-alpine            caaeda72bf8f        12 days ago         27.8MB
  1. 運行redis鏡像
[root@docker ~]# docker run --name db1 -d --rm -p 6379 redis:4-alpine
881d5648c7388449a39c67024206c5710b1538f4c941039fa3905bb601b09699
[root@docker ~]# docker exec -it db1 ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

[root@docker ~]# docker exec -it db1 /bin/sh
/data # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      
tcp        0      0 :::6379                 :::*                    LISTEN      
/data #
  1. 查看映射的端口
[root@docker ~]# docker container port db1
6379/tcp -> 0.0.0.0:32768
  1. 外網主機訪問本地宿主機容器
[root@node1 tmp]# redis-cli -h 192.168.1.106 -p 32768
192.168.1.106:32768> select 1
OK
192.168.1.106:32768[1]> set mykey hi
OK
192.168.1.106:32768[1]> keys *
1) "mykey"
192.168.1.106:32768[1]> exit
  1. 查看本地容器內是否有數據
[root@docker ~]# docker exec -it db1 /bin/sh
/data # redis-cli 
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "mykey"
127.0.0.1:6379[1]> exit
/data # exit

開啓自動端口暴露

  1. 在工做目錄下編寫Dockerfile文件
#Test Image Build
FROM redis:4-alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"
EXPOSE 6379/tcp 26379/tcp
  1. 製做鏡像文件
[root@docker images]# docker build -t expose_db:latest ./
Sending build context to Docker daemon  8.645MB
Step 1/3 : FROM redis:4-alpine
 ---> caaeda72bf8f
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Running in f43f9e43b27a
Removing intermediate container f43f9e43b27a
 ---> e98bb940a8a2
Step 3/3 : EXPOSE 6379/tcp 26379/tcp
 ---> Running in f53a9be4f661
Removing intermediate container f53a9be4f661
 ---> ea40417716a0
Successfully built ea40417716a0
Successfully tagged expose_db:latest
  1. 運行並查看效果
[root@docker images]# docker run --name a1 -d --rm -P redis_expose:latest
ad1225390f8f246cc5bde693ea99b120ee3a2f474416603b0797cda94787cc03
[root@docker images]# docker container port a1
6379/tcp -> 0.0.0.0:32772
  1. 換一臺主機鏈接數據庫查看
[root@node1 ~]# redis-cli -h 192.168.200.45 -p 32772
192.168.200.45:32772> select 1
OK
192.168.200.45:32772[1]> keys *
(empty list or set)
192.168.200.45:32772[1]> set test dockerfile
OK
192.168.200.45:32772[1]> keys *
1) "test"
192.168.200.45:32772[1]> get test
"dockerfile"
  1. 在a1容器上查看:
[root@docker images]# docker exec -it a1 /bin/sh
/data # redis-cli 
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get test
"dockerfile"

示例:驗證Dockerfile與docker run時使用-p的優先級

  1. 編輯Dockerfile
[root@docker images]# cat Dockerfile 
#Test Image Build
FROM redis:4-alpine
LABEL maintainer="lixinkuan <lixinkuan@163.com>"
EXPOSE 6379/tcp 80/tcp
  1. 製做鏡像:
[root@docker images]# docker build -t expose_port .
Sending build context to Docker daemon  8.645MB
Step 1/3 : FROM redis:4-alpine
 ---> caaeda72bf8f
Step 2/3 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 188775dd2e3e
Step 3/3 : EXPOSE 6379/tcp 80/tcp
 ---> Running in b0f5bfbaafae
Removing intermediate container b0f5bfbaafae
 ---> 165e707c2b23
Successfully built 165e707c2b23
Successfully tagged expose_port:latest
  1. 運行容器時指定要暴露的端口:
[root@docker images]# docker run --name db1 -d --rm -p 25 expose_port
e00f3e304103954c00651d44b00ae9961608900e0d5688eee4c08f140340f480
[root@docker images]# docker container port db1
25/tcp -> 0.0.0.0:32779
  1. 查看防火牆規則,只有暴露25端口的DNAT規則
[root@docker images]# iptables -t nat -nvL
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:32779 to:172.17.0.2:25

13. ENV

  • 用於爲鏡像定義所需的環境變量,並可被Dockerfile文件中位於其後的其它指令(如ENV、ADD、COPY等)所調用
  • 調用格式爲$variable_name或${variable_name}
  • Syntax
    • ENV <key> <value>
    • ENV <key>=<value> ...
  • 第一種格式中,<key>以後的全部內容均會被視做其<value>的組成部分,所以,一次只能設置一個變量
  • 第二種格式可用一次設置多個變量,每一個變量爲一個"<key>=<value>"的鍵值對,若是<value>中包含空格,能夠以反斜線()進行轉義,也可經過對<value>加引號進行標識;另外,反斜線也可用於續行
  • 定義多個變量時,建議使用第二種方式,以便在同一層中完成全部功能

示例

  1. 編輯Dockerfile文件
FROM busybox
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

ENV DOCROOT="/data/web/html/"

COPY index.html ${DOCROOT}

VOLUME ${DOCROOT}
  1. 提供index及所需掛載目錄:
[root@docker bbox]# mkdir -pv /data/web/html
mkdir: created directory ‘/data’
mkdir: created directory ‘/data/web’
mkdir: created directory ‘/data/web/html’
[root@docker bbox]# echo hello Docker > index.html
[root@docker bbox]# cat index.html
hello Docker
  1. 製做鏡像:
[root@docker bbox]# docker build -t bbox_file:latest ./
Sending build context to Docker daemon  3.072kB
Step 1/5 : FROM busybox
latest: Pulling from library/busybox
07a152489297: Pull complete 
Digest: sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Status: Downloaded newer image for busybox:latest
 ---> 8c811b4aec35
Step 2/5 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Running in 87a1f2c22ad6
Removing intermediate container 87a1f2c22ad6
 ---> 56f723d6220c
Step 3/5 : ENV DOCROOT="/data/web/html/"
 ---> Running in 21fd1fcb0474
Removing intermediate container 21fd1fcb0474
 ---> c095f8dd8418
Step 4/5 : COPY index.html ${DOCROOT}
 ---> ee77cd16629a
Step 5/5 : VOLUME ${DOCROOT}
 ---> Running in 00474fde8b85
Removing intermediate container 00474fde8b85
 ---> d51ea735fdd3
Successfully built d51ea735fdd3
Successfully tagged bbox_file:latest
  1. 運行容器並查看
[root@docker bbox]# docker run --name a1 -it --rm bbox_file:latest
/ # ls /data/web/html
index.html
/ # cat /data/web/html/index.html
hello Docker
  1. 另啓終端查看掛載的卷:
[root@docker ~]# docker volume ls
DRIVER              VOLUME NAME
local               1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbf
local               b2df5fcd0e1aa58c403d2e8f0ec880feb7dcb1a80a688697e76122adec55e789
[root@docker ~]# docker inspect -f {{.Mounts}} a1
[{volume 1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbf /var/lib/docker/volumes/1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbf/_data /data/web/html local  true }]

14. CMD與RUN

  1. CMD

    • 用於定義鏡像啓動爲容器時默認運行的應用程序。
    • 相似於RUN指令,CMD指令也可用於運行任何命令或應用程序,不過,兩者的運行時間點不一樣
    • RUN指令運行於映像文件構建過程當中,而CMD指令運行於基於Dockerfile構建出的新映像文件啓動一個容器時
    • CMD指令的首要目的在於爲啓動的容器指定默認要運行的程序,且其運行結束後,容器也將終止;不過,CMD指定的命令其能夠被docker run的命令行選項所覆蓋
    • 在Dockerfile中能夠存在多個CMD指令,但僅最後一個會生效
    • Syntax
    • CMD <command>
    • CMD [「<executable>」, 「<param1>」, 「<param2>」]
    • CMD ["<param1>","<param2>"]
    • 前兩種語法格式的意義同RUN
    • 第三種則用於爲ENTRYPOINT指令提供默認參數
  2. RUN
    • 指定docker build過程當中運行的程序。必須是鏡像中存在的命令。
    • Syntax
    • RUN <command>
    • RUN ["<executable>", "<param1>", "<param2>"]
    • 第一種格式中,<command>一般是一個shell命令,且以「/bin/sh -c」來運行它,這意味着此進程在容器中的PID不爲1,不能接收Unix信號,所以,當使用docker stop <container>命令中止容器時,此進程接收不到SIGTERM信號;
    • 第二種語法格式中的參數是一個JSON格式的數組,其中<executable>爲要運行的命令,後面的<paramN>爲傳遞給命令的選項或參數;然而,此種格式指定的命令不會以「/bin/sh -c」來發起,所以常見的shell操做如變量替換以及通配符(?,*等)替換將不會進行;不過,若是要運行的命令依賴於此shell特性的話,能夠將其替換爲相似下面的格式。
    • 示例:RUN ["/bin/bash", "-c", "<executable>", "<param1>"]

示例1:基於centos基礎鏡像建立一個運行nginx的鏡像

  1. 編輯Dockerfile文件:
FROM centos
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

COPY base.repo epel.repo /etc/yum.repos.d/

RUN yum -y install nginx \
        && yum clean all \
        && rm -rf /var/cache/yum
  1. 提供base.repo epel.repo文件:
[root@docker nginx]# wget lixinkuan.top/base.repo
--2018-06-30 11:29:08--  http://lixinkuan.top/base.repo
Resolving lixinkuan.top (lixinkuan.top)... 47.94.102.99
Connecting to lixinkuan.top (lixinkuan.top)|47.94.102.99|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 630
Saving to: ‘base.repo’

100%[=================================================================================>] 630         --.-K/s   in 0s      

2018-06-30 11:29:08 (87.9 MB/s) - ‘base.repo’ saved [630/630]

[root@docker nginx]# wget lixinkuan.top/epel.repo
--2018-06-30 11:29:16--  http://lixinkuan.top/epel.repo
Resolving lixinkuan.top (lixinkuan.top)... 47.94.102.99
Connecting to lixinkuan.top (lixinkuan.top)|47.94.102.99|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 214
Saving to: ‘epel.repo’

100%[=================================================================================>] 214         --.-K/s   in 0s      

2018-06-30 11:29:16 (44.2 MB/s) - ‘epel.repo’ saved [214/214]

[root@docker nginx]# ls
base.repo  Dockerfile  epel.repo
  1. 建立鏡像:
[root@docker nginx]# docker build -t nginx:v0.1 ./
Sending build context to Docker daemon  4.608kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
7dc0dca2b151: Pull complete 
Digest: sha256:b67d21dfe609ddacf404589e04631d90a342921e81c40aeaf3391f6717fa5322
Status: Downloaded newer image for centos:latest
 ---> 49f7960eb7e4
Step 2/4 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Running in 6b16128ed7ca
Removing intermediate container 6b16128ed7ca
 ---> b6ef19a3311f
Step 3/4 : COPY base.repo epel.repo /etc/yum.repos.d/
 ---> e571c2837442
Step 4/4 : RUN yum -y install nginx     && yum clean all    && rm -rf /var/cache/yum
 ---> Running in 445372de8e8d
Loaded plugins: fastestmirror, ovl
.....
執行安裝過程省略
...
Cleaning repos: base epel extras updates
Cleaning up everything
Maybe you want: rm -rf /var/cache/yum, to also free up space taken by orphaned data from disabled or removed repos
Cleaning up list of fastest mirrors
Removing intermediate container 445372de8e8d
 ---> 5cf6e8e3517e
Successfully built 5cf6e8e3517e
Successfully tagged nginx:v0.1
  1. 建立容器並查看:
[root@docker nginx]# docker run --name web -it nginx:v0.1
[root@5e7adf4282c1 /]# rpm -q nginx
nginx-1.12.2-2.el7.x86_64           #nginx已安裝
[root@5e7adf4282c1 /]#

示例2:以busybox製做一個掛載本地/data/web/html目錄並自動運行httpd的鏡像

  1. 在工做目錄編輯Dockerfile文件
FROM busybox
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

ENV DOCROOT="/data/web/html/"

COPY index.html ${DOCROOT}

VOLUME ${DOCROOT}

CMD /bin/httpd -f -h ${DOCROOT}
  1. 提供index.html並建立要掛載的目錄
[root@docker bbox]# echo hello Docker > index.html
[root@docker bbox]# cat index.html
hello Docker
  1. 建立鏡像文件:
[root@docker bbox]# docker build -t web:v0.1 ./
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM busybox
 ---> 8c811b4aec35
Step 2/6 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56f723d6220c
Step 3/6 : ENV DOCROOT="/data/web/html/"
 ---> Using cache
 ---> c095f8dd8418
Step 4/6 : COPY index.html ${DOCROOT}
 ---> Using cache
 ---> ee77cd16629a
Step 5/6 : VOLUME ${DOCROOT}
 ---> Using cache
 ---> d51ea735fdd3
Step 6/6 : CMD /bin/httpd -f -h ${DOCROOT}
 ---> Running in f2fa2b284306
Removing intermediate container f2fa2b284306
 ---> b8613217ad3c
Successfully built b8613217ad3c
Successfully tagged web:v0.1
  1. 以新建立的鏡像文件運行容器並查看
[root@docker bbox]# docker run --name web -d --rm web:v0.1
7b71084ebd922728ebf21d22a4e5ff3462443761c82bc22c640764c6d4925b2a
[root@docker bbox]# docker container inspect -f {{.Config.Cmd}} web
[/bin/sh -c /bin/httpd -f -h ${DOCROOT}]
[root@docker bbox]# docker exec -it web /bin/sh
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/httpd -f -h /data/web/html/
    7 root      0:00 /bin/sh
   13 root      0:00 ps aux
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN

示例3:docker run 時不運行鏡像默認進程,運行指定指令

  1. 查看當前鏡像文件:
[root@docker bbox]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
web                 v0.1                b8613217ad3c        2 hours ago         1.15MB
  1. 以web:v0.1建立容器,不運行默認命令
[root@docker bbox]# docker run --name web -it --rm web:v0.1 /bin/sh
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
    7 root      0:00 ps aux

15. ENTRYPOINT

  • 相似CMD指令的功能,用於爲容器指定默認運行程序,從而使得容器像是一個單獨的可執行程序
  • 與CMD不一樣的是,由ENTRYPOINT啓動的程序不會被docker run命令行指定的參數所覆蓋,並且,這些命令行參數會被看成參數傳遞給ENTRYPOINT指定指定的程序
    • 不過,docker run命令的--entrypoint選項的參數可覆蓋ENTRYPOINT指令指定的程序
  • Syntax
    • ENTRYPOINT <command>
    • ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
  • docker run命令傳入的命令參數會覆蓋CMD指令的內容而且附加到ENTRYPOINT命令最後作爲其參數使用
  • Dockerfile文件中也能夠存在多個ENTRYPOINT指令,但僅有最後一個會生效

示例1:

  1. 編輯Dockerfile文件
FROM busybox
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

VOLUME /data/web/html/

COPY index.html /data/web/html/

EXPOSE 80/tcp

ENTRYPOINT ["/bin/httpd","-f","-h","/data/web/html"]
  1. 建立鏡像
[root@docker bbox]# docker build -t web:v0.2 ./
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM busybox
 ---> 8c811b4aec35
Step 2/6 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56f723d6220c
Step 3/6 : VOLUME /data/web/html/
 ---> Running in 3095065d0ebb
Removing intermediate container 3095065d0ebb
 ---> 36dc68fabc6f
Step 4/6 : COPY index.html /data/web/html/
 ---> e47f81ec7728
Step 5/6 : EXPOSE 80/tcp
 ---> Running in f86f957ec882
Removing intermediate container f86f957ec882
 ---> 01a005644fe6
Step 6/6 : ENTRYPOINT ["/bin/httpd","-f","-h","/data/web/html"]
 ---> Running in 7a5f8b4f4acf
Removing intermediate container 7a5f8b4f4acf
 ---> 43d514096d34
Successfully built 43d514096d34
Successfully tagged web:v0.2
  1. 建立容器運行並查看:
[root@docker bbox]# docker exec -it web /bin/sh
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/httpd -f -h /data/web/html
    7 root      0:00 /bin/sh
   13 root      0:00 ps aux
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN      
/ #
  1. 運行容器時指定執行/bin/sh
[root@docker bbox]# docker run --name web -it --rm web:v0.2 /bin/sh
  1. 換另外一tty查看
[root@docker bbox]# docker exec -it web /bin/sh
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/httpd -f -h /data/web/html /bin/sh
    7 root      0:00 /bin/sh
   13 root      0:00 ps aux

並未執行/bin/sh,而是執行默認程序,/bin/sh被看成參數傳遞給/bin/httpd

示例:在docker run時使用entrypoint的時候更換默認運行的程序

  • --entrypoint string Overwrite the default ENTRYPOINT of the image
    1. 使用鏡像web:v0.2建立容器運行時添加--entrypoint選項
[root@docker bbox]# docker run --name web -it --rm --entrypoint /bin/sh web:v0.2
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
    7 root      0:00 ps aux
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
/ #

示例

  1. 編輯Dockerfile文件
FROM busybox
LABEL maintainer="lixinkuan <lixinkuan@163.com>"

ENV DOCROOT="/data/web/html/" MYPORT="80"

COPY index.html ${DOCROOT} 
COPY entrypoint.sh /bin/
COPY test.conf /etc/

VOLUME ${DOCROOT}

EXPOSE 80/tcp

#CMD /bin/httpd -f -h ${DOCROOT}

#CMD ["/bin/sh","-c","/bin/httpd","-f","-h","${DOCROOT}"]
ENTRYPOINT ["/bin/entrypoint.sh"]

CMD ["/bin/httpd","-f","-h","/data/web/html/"]
  1. 提供必須文件(腳本文件需加執行權限)
[root@docker bbox]# cat entrypoint.sh 
#!/bin/sh

sed -i "s@^PORT=.*@PORT=${MYPORT}@g" /etc/test.conf
exec "$@"
[root@docker bbox]# cat test.conf 
PORT=8080
  1. 製做鏡像:
[root@docker bbox]# docker build -t web:v0.3 ./
Sending build context to Docker daemon   5.12kB
Step 1/10 : FROM busybox
 ---> 8c811b4aec35
Step 2/10 : LABEL maintainer="lixinkuan <lixinkuan@163.com>"
 ---> Using cache
 ---> 56f723d6220c
Step 3/10 : ENV DOCROOT="/data/web/html/" MYPORT="80"
 ---> Running in f237100ec645
Removing intermediate container f237100ec645
 ---> f754b5dcea84
Step 4/10 : COPY index.html ${DOCROOT}
 ---> 3c31424c9b3d
Step 5/10 : COPY entrypoint.sh /bin/
 ---> 46ec2f5ede8c
Step 6/10 : COPY test.conf /etc/
 ---> 7db53e00338a
Step 7/10 : VOLUME ${DOCROOT}
 ---> Running in 5ae02469f585
Removing intermediate container 5ae02469f585
 ---> 0e1e3e966318
Step 8/10 : EXPOSE 80/tcp
 ---> Running in ae76bcf870ca
Removing intermediate container ae76bcf870ca
 ---> dea89896460d
Step 9/10 : ENTRYPOINT ["/bin/entrypoint.sh"]
 ---> Running in 6862bf4a336e
Removing intermediate container 6862bf4a336e
 ---> ca568e1ff983
Step 10/10 : CMD ["/bin/httpd","-f","-h","/data/web/html/"]
 ---> Running in 2aa5dea11848
Removing intermediate container 2aa5dea11848
 ---> 26bb44795880
Successfully built 26bb44795880
Successfully tagged web:v0.3
  1. 運行容器並查看配置文件是否被修改
[root@docker bbox]# docker run --name web -d --rm web:v0.3
6ec1f5a008e6a08047e8666f6ed3ad4673360805148789faf780baf335ee5637
[root@docker bbox]# docker exec -it web /bin/sh
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN      
/ # cat /etc/test.conf
PORT=80
/ # exit

示例:經過傳遞變量更改配置文件的方法:

[root@docker bbox]# docker run --name web1 -d --rm -e MYPORT=10080 web:v0.3
7e3b353e423839d598ee9423e881673066cf99626940b6590e78f34b7622834d
[root@docker bbox]# docker exec -it web1 /bin/sh
/ # cat /etc/test.conf 
PORT=10080
/ #
相關文章
相關標籤/搜索