Dockerfile

Dockerfile

基本结构

Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义镜像。

Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。

Docker分为四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时默认要执行的指令

例如:

# This dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: seancheng
# Command format: Instruction [arguments / command] ...

# 第一行必须指定基于的基础镜像
FROM ubuntu

# 维护者信息
LABEL MAINTAINER='seancheng xianshangxian@126.com'

# 镜像操作指令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

# 容器启动时默认要执行的指令
CMD /usr/sbin/nginx

其中,一开始必须指明所基于的镜像名称,接下来一般会说明维护者信息。
后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。
最后是CMD指令来指定运行容器时的操作指令。

指令

指令的一般格式为INSTRUCTION arguments,指令包括:

  • FROM
  • LABEL MAINTAINER
  • RUN
  • CMD
  • EXPOSE
  • ENV
  • ADD
  • COPY
  • ENTRYPOINT
  • VOLUME
  • USER
  • WORKDIR
  • ONBUILD
指令名字作用
FROM基础镜像,一切从这里开始构建
MAINTAINER镜像是谁写的,姓名+邮箱
RUN镜像构建的时候需要运行的命
ADD提供安装包位置
WORKDIR镜像的工作目录
VOLUME挂载的目录
EXPOSE暴露端口配置
CMD指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT当构建一个被继承 Dockerfile 这个时候就会运行ONBUILD 的指令
COPY类似ADD,将我们文件拷贝到镜像中
ENVENV

FROM

格式为FROM <image>FROM <image>:<tag>

第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)。

FROM centos:8(默认是最新版本)

LABEL MAINTAINER

格式为LABEL MAINTAINER <name email_address>,指定维护者信息

LABEL MAINTAINER='syblyw0806 123@qq.com'

RUN

格式为RUN <command>RUN ["executable","param1","param2"]

前者将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行。指定使用其他终端可以通过第二种方式实现,例如:

RUN ["/bin/bash","-c","echo hello"]
[root@localhost ~]# mkdir test
[root@localhost ~]# cd test/
[root@localhost test]# cat Dockerfile 
FROM centos

RUN mkdir abc

[root@localhost test]# docker build -t test:v0.1 /root/test/
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : RUN mkdir abc
 ---> Running in 1cc3cd5aa69d
Removing intermediate container 1cc3cd5aa69d
 ---> 37ec05f5a1ac
Successfully built 37ec05f5a1ac
Successfully tagged test:v0.1

[root@localhost test]# docker run -it --rm test:v0.1
[root@95d5cf5be279 /]# ls
abc  etc   lib64       mnt   root  srv  usr
bin  home  lost+found  opt   run   sys  var
dev  lib   media       proc  sbin  tmp

[root@localhost test]# cat Dockerfile 
FROM centos

RUN ["/usr/bin/mkdir","-p","/hehe/xixi/haha"]

[root@localhost test]# docker build -t test:v0.2 /root/test/
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : RUN ["/usr/bin/mkdir","-p","/hehe/xixi/haha"]
 ---> Running in 36392aa44fb9
Removing intermediate container 36392aa44fb9
 ---> baf7fce2f1d7
Successfully built baf7fce2f1d7
Successfully tagged test:v0.2

[root@localhost test]# docker run -it --rm test:v0.2
[root@4d9d5dfddfc7 /]# ls
bin  hehe  lib64       mnt   root  srv  usr
dev  home  lost+found  opt   run   sys  var
etc  lib   media       proc  sbin  tmp
[root@4d9d5dfddfc7 /]# cd hehe/
[root@4d9d5dfddfc7 hehe]# ls xixi/
haha

每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行,例如:

RUN echo "hello world\nhello tom" > /tmp/abc && \
    cat /tmp/abc
[root@localhost test]# cat Dockerfile
FROM centos

RUN echo "hello world\nhello tom" > /tmp/abc && \
    cat /tmp/abc

CMD

CMD支持三种格式:

  • CMD ["executable","param1","param2"]使用exec执行,推荐方式
  • CMD command param1 param2在/bin/sh中执行,提供给需要交互的应用
  • CMD ["param1","param2"]提供给ENTRYPOINT的默认参数

CMD用于指定启动容器时默认要执行的命令,每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。

// 使用CMD第二种格式
[root@localhost test]# cat Dockerfile 
FROM centos

CMD sleep 600	// 当CMD只有这一条的时候就执行当前命令

[root@localhost test]# docker build -t test:v0.4 /root/test
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : CMD sleep 600
 ---> Running in c8334041d0d8
Removing intermediate container c8334041d0d8
 ---> 04b29b18007f
Successfully built 04b29b18007f
Successfully tagged test:v0.4

[root@localhost test]# docker run -itd --rm test:v0.4
e332f6d2b7e49bfd1b536ba8d4c2dd8fa2473b84b2fd33280ba5d503b493f429
[root@localhost test]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
e332f6d2b7e4   test:v0.4   "/bin/sh -c 'sleep 6…"   3 seconds ago   Up 2 seconds             trusting_chaplygin

[root@localhost test]# cat Dockerfile 
FROM centos

CMD sleep 600
CMD sleep 700
CMD sleep 800 		// 当CMD有三条的时候,只会执行最后一条命令

[root@localhost test]# docker build -t test:v0.5 /root/test/
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : CMD sleep 600
 ---> Using cache
 ---> 04b29b18007f
Step 3/4 : CMD sleep 700
 ---> Running in 0894d1cb0ee8
Removing intermediate container 0894d1cb0ee8
 ---> c8dc64c9276e
Step 4/4 : CMD sleep 800
 ---> Running in a8d504b7b9b1
Removing intermediate container a8d504b7b9b1
 ---> a1bb66d8c5d2
Successfully built a1bb66d8c5d2
Successfully tagged test:v0.5

[root@localhost test]# docker run -itd --rm test:v0.5
f95fb66e5c16a446984a2e88648a85465deb7569e82664997eebc7dad960064d
[root@localhost test]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
f95fb66e5c16   test:v0.5   "/bin/sh -c 'sleep 8…"   2 seconds ago   Up 2 seconds             vigorous_ritchie

如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。

[root@localhost test]# docker images
[root@localhost test]# cat Dockerfile 
FROM centos

CMD ["sleep","400"]
[root@localhost test]# docker build -t test:v0.8 /root/test/
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : CMD ["sleep","400"]
 ---> Running in faffd15f9944
Removing intermediate container faffd15f9944
 ---> 0c1864ac64c6
Successfully built 0c1864ac64c6
Successfully tagged test:v0.8

// 没有覆盖是这样的
[root@localhost test]# docker run -itd --rm test:v0.8
b4e6f4625d04b824cf7dc324c50ef603c31e3366464006bc067ba9b5a4a7288d
[root@localhost test]# docker ps
CONTAINER ID   IMAGE       COMMAND       CREATED         STATUS         PORTS     NAMES
b4e6f4625d04   test:v0.8   "sleep 400"   5 seconds ago   Up 4 seconds             strange_chandrasekhar
[root@localhost test]# docker rm -f b4e6f4625d04
b4e6f4625d04

// 覆盖之后 sleep 400 变成 /bin/bash
[root@localhost test]# docker run -itd --rm test:v0.8 /bin/bash
fbf0ec0e58fdf49358aca74efd2575464724fef5afa15890cc93193916016e65
[root@localhost test]# docker ps
CONTAINER ID   IMAGE       COMMAND       CREATED         STATUS         PORTS     NAMES
fbf0ec0e58fd   test:v0.8   "/bin/bash"   5 seconds ago   Up 4 seconds             naughty_albattani

使用CMD第一种格式在前台运行httpd(推荐使用这种格式)

[root@localhost test]# cat Dockerfile 
FROM centos

RUN ["/usr/bin/dnf","-y","install","httpd"]

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

[root@localhost test]# docker build -t test:v0.7 /root/test/
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM centos
 ---> 5d0da3dc9764
Step 2/3 : RUN ["/usr/bin/dnf","-y","install","httpd"]
 ---> Using cache
 ---> e044e1eda4ef
Step 3/3 : CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
 ---> Running in b717a91a43cc
Removing intermediate container b717a91a43cc
 ---> db064b1650f0
Successfully built db064b1650f0
Successfully tagged test:v0.7

// 在前台运行
[root@localhost test]# docker run -it --rm test:v0.7
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
6ac21f0b46b6   test:v0.7   "/usr/sbin/httpd -D …"   5 seconds ago   Up 4 seconds             sleepy_wu

[root@localhost test]# docker inspect b1c2a92754ec
            "Cmd": [
                "/usr/sbin/httpd",
                "-D",
                "FOREGROUND"

EXPOSE

格式为EXPOSE <port> [<port>...]
例如:

EXPOSE 22 80 8443

EXPOSE用于告诉Docker服务器容器暴露的端口号,供互联系统使用。

[root@localhost test]# cat Dockerfile 
FROM centos

RUN ["/usr/bin/dnf","-y","install","httpd"]

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

EXPOSE 80	// 只是用来暴露端口,用来看的

[root@localhost test]# docker build -t test:v0.1 /root/test/

[root@localhost test]# docker run -it --rm test:v0.1
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
0fb783f7177e   test:v0.1   "/usr/sbin/httpd -D …"   5 seconds ago   Up 3 seconds   80/tcp    adoring_sutherland			// 80端口已暴露

[root@localhost ~]# docker inspect 0fb783f7177e
            "ExposedPorts": {
                "80/tcp": {}
[root@localhost test]# cat Dockerfile 
FROM centos

RUN ["/usr/bin/dnf","-y","install","httpd"]

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

EXPOSE 80 443	// 暴露80端口和443端口

[root@localhost test]# docker build -t test:v0.2 /root/test/
Sending build context to Docker daemon  9.878MB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : RUN ["/usr/bin/dnf","-y","install","httpd"]
 ---> Using cache
 ---> 1f572fe047ea
Step 3/4 : CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
 ---> Using cache
 ---> aee89390c009
Step 4/4 : EXPOSE 80 443
 ---> Running in 9c07b2de3205
Removing intermediate container 9c07b2de3205
 ---> 9851cc87915a
Successfully built 9851cc87915a
Successfully tagged test:v0.2

[root@localhost test]# docker run -d test:v0.2
00cef3fbd5a27ac9c9c26ad2bc00378ef74a77a4747dce53ddc4a82fdcd3868d

[root@localhost test]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS             NAMES
00cef3fbd5a2   test:v0.2   "/usr/sbin/httpd -D …"   7 seconds ago   Up 6 seconds   80/tcp, 443/tcp   laughing_snyder	// 虽然暴露了443端口,但是实际主机没有443端口,无法访问。所以EXPOSE主要是用来暴露以后用的到端口

在启动容器时通过-P,Docker主机会自动分配一个端口转发到指定的端口;
使用-p则可以具体指定哪个本地端口映射过来。

ENV

格式为ENV <key> <value>。指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持。例如:

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4	// 定义变量
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && ...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH	// 定义环境变量

指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持。例如:

[root@localhost test]# cat Dockerfile 
FROM centos

ENV NAME syb	// 创建一个变量NAME

EXPOSE 80 443

[root@localhost test]# docker build -t test:v0.3 /root/test/
Sending build context to Docker daemon  9.878MB
Step 1/3 : FROM centos
 ---> 5d0da3dc9764
Step 2/3 : ENV NAME syb
 ---> Running in 1b6de8792c77
Removing intermediate container 1b6de8792c77
 ---> 53e1f2c60b44
Step 3/3 : EXPOSE 80 443
 ---> Running in bec56994993a
Removing intermediate container bec56994993a
 ---> 79c1d18361d4
Successfully built 79c1d18361d4
Successfully tagged test:v0.3

[root@localhost test]# docker run -it --rm test:v0.3
[root@f1ecb8394940 /]# echo $NAME
syb
[root@localhost test]# cat Dockerfile 
FROM centos

ENV PATH /usr/local/apache/bin:$PATH	// 创建一个环境变量

[root@localhost test]# docker build -t test:v0.4 /root/test/
Sending build context to Docker daemon  9.878MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ENV PATH /usr/local/apache/bin:$PATH
 ---> Running in 23e518f2d5c2
Removing intermediate container 23e518f2d5c2
 ---> b4f926e2cc3b
Successfully built b4f926e2cc3b
Successfully tagged test:v0.4

[root@localhost test]# docker run -it --rm test:v0.4
[root@7a0d85cdd435 /]# echo $PATH
/usr/local/apache/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

ADD

格式为ADD <src> <dest>

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] 

该命令将复制指定的到容器中的。其中可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一个URL;还可以是一个tar文件(会自动解压为目录)。
ADD指令跟COPY类似,不过它还支持使用tar文件和URL路径。

当拷贝的源文件是tar文件时,会自动展开为一个目录并拷贝进新的镜像中;然而通过URL获取到的tar文件不会自动展开。

主机可以联网的情况下,docker build可以将网络上的某文件引用下载并打包到新的镜像

# 转移文件
// 创建一个abc文件
[root@localhost test]# echo "hello syb" > abc

// 创建files目录,上传httpd包上去
[root@localhost test]# mkdir files
[root@localhost test]# cd files/
[root@localhost files]# ls
httpd-2.4.51.tar.gz

[root@localhost test]# ls
Dockerfile  abc  files

[root@localhost test]# cp -r files/httpd-2.4.51.tar.gz .
[root@localhost test]# ls
Dockerfile  abc  files  httpd-2.4.51.tar.gz

// 运行dockerfile创建一个test:v0.5镜像
[root@localhost ~]# docker build -t test:v0.5 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ADD abc /opt
 ---> 957a71bf1809
Successfully built 957a71bf1809
Successfully tagged test:v0.5

[root@localhost test]# cat Dockerfile 
FROM centos

ADD abc /opt

/ / abc文件已放到容器opt目录里面
[root@localhost ~]# docker run -it --rm test:v0.5
[root@0b6780cd1e88 /]# ls /opt/
abc
[root@0b6780cd1e88 /]# cat /opt/abc 
hello syb
# 转移目录里面的内容
[root@localhost test]# cat Dockerfile 
FROM centos

ADD files /opt	// 同步文件里面的内容

[root@localhost ~]# docker build -t test:v0.6 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ADD files /opt
 ---> fcddfc756666
Successfully built fcddfc756666
Successfully tagged test:v0.6

[root@localhost ~]# docker run -it --rm test:v0.6
[root@4ce0cef18abb /]# ls /opt/		// files目录里面的httpd安装包已放到容器的opt里面
httpd-2.4.51.tar.gz
# 同步tar文件,会自动解压为目录

[root@localhost test]# cat Dockerfile 
FROM centos

ADD httpd-2.4.51.tar.gz /opt

[root@localhost ~]# docker build -t test:v0.7 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ADD httpd-2.4.51.tar.gz /opt
 ---> 14ec6f6ac9c5
Successfully built 14ec6f6ac9c5
Successfully tagged test:v0.7

[root@localhost ~]# docker run -it --rm test:v0.7
[root@d83e68526471 /]# ls /opt/
httpd-2.4.51	// 安装包自动解压为目录
# url
[root@localhost test]# cat Dockerfile 
FROM centos

ADD https://downloads.apache.org/httpd/httpd-2.4.51.tar.gz /opt	// 写入url地址

[root@localhost ~]# docker build -t test:v0.8 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ADD https://downloads.apache.org/httpd/httpd-2.4.51.tar.gz /opt
Downloading  9.874MB/9.874MB
 ---> 76db49dd904f
Successfully built 76db49dd904f
Successfully tagged test:v0.8

[root@localhost ~]# docker run -it --rm test:v0.8
[root@1aef8e2649b1 /]# ls /opt/
httpd-2.4.51.tar.gz				// 直接下载,把下载好的安装包放到容器里面

// 还可以配置ENV使用,以后下载包直接更换版本就行
[root@localhost test]# cat Dockerfile 
FROM centos

ENV version 2.4.48

ADD https://downloads.apache.org/httpd/httpd-${version}.tar.gz /opt

[root@localhost ~]# docker build -t test:v0.9 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/3 : FROM centos
 ---> 5d0da3dc9764
Step 2/3 : ENV version 2.4.48
 ---> Using cache
 ---> 75f478b3f205
Step 3/3 : ADD https://downloads.apache.org/httpd/httpd-${version}.tar.gz /opt
Downloading  9.174MB/9.174MB
 ---> 22f807c2e840
Successfully built 22f807c2e840
Successfully tagged test:v0.9

[root@localhost ~]# docker run -it --rm test:v0.9
[root@f36ea252908c /]# ls /opt/
httpd-2.4.48.tar.gz

COPY

格式为COPY <src> <dest>

COPY [--chown=<user>:<group>] <src>...  <dest>
COPY [--chown=<user>:<group>] ["<src>",...  "<dest>"]

复制本地主机的(为Dockerfile所在目录的相对路径,文件或目录)为容器中的。目标路径不存在时会自动创建。

使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等

如果是目录,只复制目录内容,而非目录本身

当使用本地目录为源目录时,推荐使用COPY。

[root@localhost test]# ls
Dockerfile  abc  files httpd-2.4.51.tar.gz

// 编写COPY指令
[root@localhost test]# cat Dockerfile 
FROM centos

COPY abc /opt
COPY files /opt

// 执行Dockerfile
[root@localhost test]# docker build -t test:v0.1 /root/test
Sending build context to Docker daemon  9.878MB
Step 1/3 : FROM centos
 ---> 5d0da3dc9764
Step 2/3 : COPY abc /opt
 ---> 1348d8d8d436
Step 3/3 : COPY files /opt
 ---> ecb883e5c2f6
Successfully built ecb883e5c2f6
Successfully tagged test:v0.1

// 运行容器查看
[root@localhost test]# docker run -it --rm test:v0.1 /bin/bash
[root@3962b08df6b7 /]# ls
bin  home   lost+found  opt   run   sys  var
dev  lib    media       proc  sbin  tmp
etc  lib64  mnt         root  srv   usr
[root@3962b08df6b7 /]# ls /opt/
abc  httpd-2.4.51.tar.gz
[root@3962b08df6b7 /]# cat /opt/abc 
hello syb		// copy成功将abc文件和files目录的安装包复制过去了

copy复制tar安装包不会解压,是原封不动复制过去

[root@localhost test]# cat Dockerfile 
FROM centos

COPY httpd-2.4.51.tar.gz /opt

[root@localhost ~]# docker build -t test:v0.10 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : COPY httpd-2.4.51.tar.gz /opt
 ---> 461119937a33
Successfully built 461119937a33
Successfully tagged test:v0.10

[root@localhost ~]# docker run -it --rm test:v0.10
[root@e3ab18c4c712 /]# ls /opt/
httpd-2.4.51.tar.gz
[root@localhost test]# cat Dockerfile 
FROM centos

COPY httpd-2.4.51.tar.gz /files	  // 把一个压缩包放在一个不存在的目录,没有加上/files/左斜线,他会以为你把它放到根下面,改名为files

# COPY httpd-2.4.51.tar.gz /files/:我们需要这么写

[root@localhost ~]# docker build -t test:v0.1 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : COPY httpd-2.4.51.tar.gz /files
 ---> 80cc38ca09c5
Successfully built 80cc38ca09c5
Successfully tagged test:v0.1

[root@localhost ~]# docker run -it --rm test:v0.1
[root@36e10cefa2d3 /]# ls
bin  files  lib64       mnt   root  srv  usr
dev  home   lost+found  opt   run   sys  var
etc  lib    media       proc  sbin  tmp

[root@36e10cefa2d3 /]# ls -l /files 
-rw-r--r--. 1 root root 9873874 Dec  8 08:07 /files

[root@36e10cefa2d3 /]# mv files tmp/

[root@36e10cefa2d3 /]# ls /tmp/
files               ks-script-o23i7rc2
ks-script-4luisyla  ks-script-x6ei4wuu

[root@36e10cefa2d3 /]# cd tmp/ 
[root@36e10cefa2d3 tmp]# tar xf files 
[root@36e10cefa2d3 tmp]# ls
files         ks-script-4luisyla  ks-script-x6ei4wuu
httpd-2.4.51  ks-script-o23i7rc2

ENTRYPOINT

ENTRYPOINT有两种格式:

  • ENTRYPOINT [“executable”,“param1”,“param2”]
  • ENTRYPOINT command param1 param2(在shell中执行)

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,如果在docker run的后面提供了参数会被当作参数传递给 ENTRYPOINT 指令指定的程序。

每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT时,只有最后一个生效。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

不希望程序被修改我们要使用 ENTRYPOINT指定;希望程序可以被修改用CMD指定

// 使用第二种格式
[root@localhost test]# cat Dockerfile 
FROM centos

RUN rm -rf /etc/yum.repos.d/* && \
    curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-$(awk -F'"' 'NR==2{print $2}' /etc/os-release).repo && \
    sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo && \
    dnf clean all && \
    dnf -y install httpd

ENTRYPOINT /usr/sbin/httpd -D FOREGROUND

[root@localhost ~]# docker build -t test:v0.3 /root/test/
......以上省略
Removing intermediate container 6ba4992806c8
 ---> 74e2e4ee1976
Step 3/3 : ENTRYPOINT /usr/sbin/httpd -D FOREGROUND
 ---> Running in 29ff973fff66
Removing intermediate container 29ff973fff66
 ---> e784c6e2a463
Successfully built e784c6e2a463
Successfully tagged test:v0.3

[root@localhost ~]# docker run -it --rm test:v0.3
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
d9607d467c21   test:v0.3   "/bin/sh -c '/usr/sb…"   8 seconds ago   Up 7 seconds             stupefied_buck		// 第二种格式使用的/bin/sh 运行
// 使用第一种格式(推荐使用这一种)
[root@localhost test]# cat Dockerfile 
FROM centos

RUN rm -rf /etc/yum.repos.d/* && \
    curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-$(awk -F'"' 'NR==2{print $2}' /etc/os-release).repo && \
    sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo && \
    dnf clean all && \
    dnf -y install httpd

ENTRYPOINT ["/usr/sbin/httpd","-D","FOREGROUND"]

[root@localhost ~]# docker build -t test:v0.4 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/3 : FROM centos
 ---> 5d0da3dc9764
Step 2/3 : RUN rm -rf /etc/yum.repos.d/* &&     curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-$(awk -F'"' 'NR==2{print $2}' /etc/os-release).repo &&     sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo &&     dnf clean all &&     dnf -y install httpd
 ---> Using cache
 ---> 74e2e4ee1976
Step 3/3 : ENTRYPOINT ["/usr/sbin/httpd","-D","FOREGROUND"]
 ---> Running in 765b40148b47
Removing intermediate container 765b40148b47
 ---> fad18b563a3b
Successfully built fad18b563a3b
Successfully tagged test:v0.4


[root@localhost ~]# docker run -it --rm test:v0.4
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS     NAMES
96aa97853703   test:v0.4   "/usr/sbin/httpd -D …"   5 seconds ago   Up 4 seconds             cool_swanson	// 直接使用/usr/sbin/httpd 启动
// 第一种格式还可以配合CMD这样写
[root@localhost test]# cat Dockerfile 
FROM centos

RUN rm -rf /etc/yum.repos.d/* && \
    curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-$(awk -F'"' 'NR==2{print $2}' /etc/os-release).repo && \
    sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo && \
    dnf clean all && \
    dnf -y install httpd

CMD ["-D","FOREGROUND"]				// 如果这里注释掉CMD,服务将会在后台运行
ENTRYPOINT ["/usr/sbin/httpd"]		// 以为ENTRYPOINT是入口点,CMD写在前面也没事

[root@localhost ~]# docker build -t test:v0.5 /root/test/
Sending build context to Docker daemon  19.75MB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : RUN rm -rf /etc/yum.repos.d/* &&     curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-$(awk -F'"' 'NR==2{print $2}' /etc/os-release).repo &&     sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo &&     dnf clean all &&     dnf -y install httpd
 ---> Using cache
 ---> 74e2e4ee1976
Step 3/4 : CMD ["-D","FOREGROUND"]
 ---> Running in a29ef29af0e1
Removing intermediate container a29ef29af0e1
 ---> 3320917ce061
Step 4/4 : ENTRYPOINT ["/usr/sbin/httpd"]
 ---> Running in c3cd93e9b5ca
Removing intermediate container c3cd93e9b5ca
 ---> 2ca91ccaa9bf
Successfully built 2ca91ccaa9bf
Successfully tagged test:v0.5

// 前台运行
[root@localhost ~]# docker run -it --rm test:v0.5
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS     NAMES
24d76ce0c59c   test:v0.5   "/usr/sbin/httpd -D …"   17 seconds ago   Up 15 seconds             flamboyant_zhukovsky		// 直接使用/usr/sbin/httpd 启动


// 单独使用CMD启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令
// 配合ENTRYPOINT则无法指定,无法改变,会报错(ENTRYPOINT里面写了什么运行方式,就只能用这个运行方式)
[root@localhost ~]# docker run -it --rm test:v0.5 /bin/bash
Usage: /usr/sbin/httpd [-D name] [-d directory] [-f file]

// 加上-v查看版本
[root@localhost ~]# docker run -it --rm test:v0.5 -v
Server version: Apache/2.4.37 (centos)
Server built:   Nov 12 2021 04:57:27

VOLUME

格式为VOLUME ["/data"]

创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

USER

格式为USER daemon

指定运行容器时的用户名或UID,后续的RUN也会使用指定用户。

当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:

RUN groupadd -r postgres && useradd -r -g postgres postgres

要临时获取管理员权限可以使用gosu,而不推荐sudo。如果不指定,容器默认是root运行。

WORKDIR

格式为WORKDIR /path/to/workdir

为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。
可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

则最终路径为/a/b/c。

ONBUILD

格式为ONBUILD [INSTRUCTION]

配置当所创建的镜像作为其他镜像的基础镜像时,所执行的操作指令。

例如,Dockerfile使用如下的内容创建了镜像image-A

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

此时,如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像时,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令。

FROM image-A

# Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用ONBUILD指令的镜像,推荐在标签中注明,例如ruby:1.9-onbuild。

[root@localhost opt]# tree test/
test/
|-- Dockerfile
`-- files
    `-- httpd-2.4.51.tar.gz

1 directory, 2 files

[root@localhost opt]# ls
apache  containerd  test


[root@localhost opt]# cat test/Dockerfile 
FROM centos
ONBUILD ADD files/httpd-2.4.51.tar.gz /usr/src

[root@localhost opt]# docker build -t download_httpd:v0.2 test
Sending build context to Docker daemon  9.877MB
Step 1/2 : FROM centos
 ---> 5d0da3dc9764
Step 2/2 : ONBUILD ADD files/httpd-2.4.51.tar.gz /usr/src
 ---> Running in b300c5e6a190
Removing intermediate container b300c5e6a190
 ---> 921bd96ab3f3
Successfully built 921bd96ab3f3
Successfully tagged download_httpd:v0.2


[root@localhost opt]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED          SIZE
download_httpd     v0.2      921bd96ab3f3   2 minutes ago    231MB

[root@localhost opt]# docker run -it --rm download_httpd:v0.2 /bin/sh
sh-4.4# ls /usr/src/
debug  kernels		// 目录里面并没有httpd解压目录

[root@localhost opt]# cp -r test/files/ apache/

[root@localhost opt]# cat apache/Dockerfile 
FROM download_httpd:v0.2	// 来自于ownload_httpd:v0.2镜像

[root@localhost opt]# docker build -t httpd:v0.2 apacheSending build context to Docker daemon  9.877MB
Step 1/1 : FROM download_httpd:v0.2
# Executing 1 build trigger
 ---> 75406791769a
Successfully built 75406791769a
Successfully tagged httpd:v0.2

[root@localhost opt]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED          SIZE
httpd              v0.2      75406791769a   18 seconds ago   273MB
download_httpd     v0.2      921bd96ab3f3   4 minutes ago    231MB

[root@localhost opt]# rm -rf test/files/
[root@localhost opt]# tree 
.
|-- apache
|   |-- Dockerfile
|   `-- files
|       `-- httpd-2.4.51.tar.gz
|-- containerd
|   |-- bin
|   `-- lib
`-- test
    `-- Dockerfile


[root@localhost opt]# docker build -t httpd:v0.3 apache
Sending build context to Docker daemon  9.877MB
Step 1/1 : FROM download_httpd:v0.2
# Executing 1 build trigger
 ---> Using cache
 ---> 75406791769a
Successfully built 75406791769a
Successfully tagged httpd:v0.3

[root@localhost opt]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED              SIZE
httpd              v0.2      75406791769a   About a minute ago   273MB
httpd              v0.3      75406791769a   About a minute ago   273MB
download_httpd     v0.2      921bd96ab3f3   5 minutes ago        231MB


[root@localhost opt]# docker run -it --rm httpd:v0.2
[root@1822cc3cd822 /]# ls /usr/s
ls: cannot access '/usr/s': No such file or directory
[root@1822cc3cd822 /]# ls /usr/src/
debug  httpd-2.4.51  kernels	// 添加了httpd解压目录

[root@localhost opt]# docker run -it --rm httpd:v0.3
[root@f12844caa8ef /]# ls /usr/src/
debug  httpd-2.4.51  kernels

创建镜像

编写完成Dockerfile后,可以通过docker build命令来创建镜像。

基本的格式为docker build [选项] 路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下所有内容发送给Docker服务端,由服务端来创建镜像。因此一般建议放置Dockerfile的目录为空目录。

另外,可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让Docker忽略路径下的目录和文件。

要指定镜像的标签信息,可以通过-t选项。

例如,指定Dockerfile所在路径为/tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令:

docker build -t build_repo/first_image /tmp/docker_builder/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值