您的位置:首页 > 运维架构 > Docker

常用Dockerbuild命令

2018-08-16 11:53 477 查看

基于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

示例

只修改一个镜像的FROM、LABEL

  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>事先不存在,它将会被自动创建,这包括其父目录路径

    示例:复制单个文件

    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>

    示例:复制目录下的多个文件至目录

    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

    示例:使用数组格式创建配置文件

    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>

    示例:下载一个文件至镜像文件

    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一个压缩包至镜像文件

    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

    示例

    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时,宿主机内容器若要被外网主机访问的情况

    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
        使用镜像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
    / #
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签:  dockerbuild 命令