Docker系列之四:Dockerfile的使用

系列链接

Docker系列之一:Docker介绍及在Ubuntu上安装

Docker系列之二:Docker 入门

Docker系列之三:使用Docker镜像和仓库

Docker系列之四:Dockerfile的使用

Docker系列之五:Volume 卷的使用——以Redis为例

Docker系列之六:Volume 卷的使用——在Dockerfile中的用法

Docker系列之七:Docker 网络(内部网络、容器之间的连接)

Docker系列之八:在Dockerfile中使用多段构建Muti-stage build

Docker系列之九:Docker用于持续集成,构建Jenkins和Docker服务器

Docker系列之十:Docker Compose的使用

简介

Dockerfile是自动构建Docker镜像的配置文件,用户可以使用Dockerfile快速创建自定义的镜像。

Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。Dockerfile 是由一行行命令语句组成,并且支持已 # 开头的注释行。

Dockerfile 分为四个部分:

  • 基础镜像(父镜像)信息指令 FROM。

  • 维护者信息指令 MAINTAINER。

  • 镜像操作指令 RUN 、EVN 、ADD 和 WORKDIR 等。

  • 容器启动指令 CMD 、ENTRYPOINT 和 USER 等。

例子

先看个最简单的例子吧

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# ls
Dockerfile  index.html

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# cat Dockerfile
#nginx基础镜像
FROM nginx
#指定工作路径
WORKDIR /usr/share/nginx/html
#将前前路径下的所有文件都COPY到工作路径下
COPY . .
#EXPOSE 命令用来指定对外开放的端口,实际用处不大,可不写
EXPOSE 80

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# cat index.html
<h1>hello</h1>

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# docker build --tag firstdemo .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM nginx
 ---> dbfc48660aeb
Step 2/4 : WORKDIR /usr/share/nginx/html
 ---> Using cache
 ---> 49eb0195ae40
Step 3/4 : COPY . .
 ---> 38b65eaf39e1
Step 4/4 : EXPOSE 80
 ---> Running in 48478a97934d
Removing intermediate container 48478a97934d
 ---> e16afe49d571
Successfully built e16afe49d571
Successfully tagged firstdemo:latest

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# docker run -itd -p 91:80 firstdemo
abd51e5f69b37bc25bbe57d55da41a7bc53fd373c4842d601371956213354261

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# curl localhost:91
<h1>hello</h1>

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
firstdemo               latest              e16afe49d571        30 seconds ago      109MB
nginx                   latest              dbfc48660aeb        4 weeks ago         109MB

root@iZbp13z6cxj72rb7bxf0smZ:/home/cong/DockerDemo# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
abd51e5f69b3        firstdemo           "nginx -g 'daemon of…"   17 seconds ago      Up 16 seconds       0.0.0.0:91->80/tcp       heuristic_panini

常用命令的讲解

FROM

FROM 是用于指定基础的 images ,一般格式为 FROM 。所有的 Dockerfile 都应该以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像。可以在同一个 Dockerfile 中多次使用 FROM 命令用于创建多个镜像。

MAINTAINER

MAINTAINER 是用于指定镜像创建者和联系方式,一般格式为 MAINTAINER。

COPY

COPY 是用于复制本地主机的(为 Dockerfile 所在目录的相对路径)到容器中的。当使用本地目录为源目录时,推荐使用 COPY 。一般格式为 COPY。例如我们要拷贝当前目录到容器中的 /app 目录下,我们可以这样操作:COPY ./app

WORKDIR

WORKDIR 用于配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。一般格式为 WORKDIR /path/to/work/dir。

RUN

RUN 用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为 RUN。例如我们要安装 Python 依赖包,我们做法如下:RUN pip install -r requirements.txt

EXPOSE

EXPOSE 命令用来指定对外开放的端口。一般格式为 EXPOSE[...]。例如上面那个例子,开放80端口:EXPOSE 80

ENTRYPOINT

ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

ENTRYPOINT 命令也有两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 Exec 形式。

  • ENTRYPOINT command param1 param2 :Shell 形式。

CMD

CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。

不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为 ENTRYPOINT 的参数。

CMD 命令有三种格式:

  • CMD ["executable","param1","param2"]:推荐使用的 exec 形式。

  • CMD ["param1","param2"]:无可执行程序形式。

  • CMD command param1 param2:Shell 形式。

一个 Dockerfile 中只能有一个 CMD,如果有多个,则最后一个生效。而 CMD 的 Shell 形式默认调用 /bin/sh -c 执行命令。

CMD 命令会被 Docker 命令行传入的参数覆盖:docker run nginx /bin/echo Hello Docker 会把 CMD 里的命令覆盖。

 例子2

看下面的命令

root@iZbp10cx0jnf0aZ:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新资源库
RUN apt-get -yqq update
#安装curl
RUN apt-get install iputils-ping -y

#安装ifconfig
RUN apt-get install net-tools -y

RUN echo aaaa

CMD echo bbbbb

CMD echo ccccc

ENTRYPOINT hostname

root@iZbp10cx0jnf0aZ:/home/cong# docker build -t second .
Sending build context to Docker daemon  10.56MB
Step 1/10 : FROM ubuntu
latest: Pulling from library/ubuntu
Status: Downloaded newer image for ubuntu:latest
 ---> ea4c82dcd15a
Step 2/10 : MAINTAINER Jason "[email protected]"
 ---> Running in fae67d94ec2d
Removing intermediate container fae67d94ec2d
 ---> e7f2fd8da425
Step 3/10 : ENV REFRESHED_AT 2018-11-14
 ---> Running in a252947b9ff0
Removing intermediate container a252947b9ff0
 ---> 9f578f16661d
Step 4/10 : RUN apt-get -yqq update
 ---> Running in ee0f56995d2b
Removing intermediate container ee0f56995d2b
 ---> 84eb3d468051
Step 5/10 : RUN apt-get install iputils-ping -y
 ---> Running in e78b3707f5d0
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container e78b3707f5d0
 ---> ace6ee693276
Step 6/10 : RUN apt-get install net-tools -y
 ---> Running in 8a0e627277ed
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
  net-tools
0 upgraded, 1 newly installed, 0 to remove and 5 not upgraded.
Need to get 194 kB of archives.
After this operation, 803 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 net-tools amd64 1.60+git20161116.90da8a0-1ubuntu1 [194 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 194 kB in 2s (89.6 kB/s)
Selecting previously unselected package net-tools.
(Reading database ... 4081 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20161116.90da8a0-1ubuntu1_amd64.deb ...
Unpacking net-tools (1.60+git20161116.90da8a0-1ubuntu1) ...
Setting up net-tools (1.60+git20161116.90da8a0-1ubuntu1) ...
Removing intermediate container 8a0e627277ed
 ---> 639597a35e80
Step 7/10 : RUN echo aaaa
 ---> Running in 8507b4f441ab
aaaa
Removing intermediate container 8507b4f441ab
 ---> 5d4d0e9d04c9
Step 8/10 : CMD echo bbbbb
 ---> Running in 8547b9d26a38
Removing intermediate container 8547b9d26a38
 ---> 04b07e79a65a
Step 9/10 : CMD echo ccccc
 ---> Running in dca4181b0c76
Removing intermediate container dca4181b0c76
 ---> 885f695315c9
Step 10/10 : ENTRYPOINT hostname
 ---> Running in ec1672da6ab5
Removing intermediate container ec1672da6ab5
 ---> b2d4ae15cf42
Successfully built b2d4ae15cf42
Successfully tagged second:latest
root@iZbp10cx0jnf0aZ:/home/cong# docker run -it second
dafc85f4d1c8

#这里面后面加echo ddddd不起作用,因为entrypoint 指定的是uname,在uname可执行程序下,不能执行echo
root@iZbp10cx0jnf0aZ:/home/cong# docker run -it second echo ddddd
554f4d2e53f3

可以看出上面的 RUN aaaaa,在build时被打印出来了,说明run是用于容器内容的执行命令,但CMD echo bbbbb和CMD echo cccc在任何条件下都没有被打印出来,因为它被entrypoint覆盖了,我们直接run之后,可以看到它执行了entrypoint里的hostname命令。

我们尝试修改一下,将entrypoint删除后,再执行,得出如下结果,说明CMD的最后一个命令被执行了。

root@iZbp10cx0jnf0aZ:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新资源库
RUN apt-get -yqq update
#安装curl
RUN apt-get install iputils-ping -y

#安装ifconfig
RUN apt-get install net-tools -y

RUN echo aaaa

CMD echo bbbbb

CMD echo ccccc

root@iZbp10cx0jnf0aZ:/home/cong# docker build -t second .

root@iZbp10cx0jnf0aZ:/home/cong# docker run -it second
ccccc

#这里dockerfile里面的 cmd命令都被覆盖了
root@iZbp10cx0jnf0aZ:/home/cong# docker run -it second echo ddddd
ddddd

我们重新将Entrypoint 加入,并指定/bin/bash,作为可执行程序

root@iZbp10cx0jnf0aZ:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新资源库
RUN apt-get -yqq update
#安装curl
RUN apt-get install iputils-ping -y

#安装ifconfig
RUN apt-get install net-tools -y

RUN echo aaaa

CMD echo bbbbb

CMD echo ccccc

ENTRYPOINT /bin/bash

root@iZbp10cx0jnf0aZ:/home/cong# docker build -t second .

root@iZbp10cx0jnf0aZ:/home/cong# docker run -it second
# 直接进入了容器里的bash命令终端
root@aefdde7d806a:/# 

讲到这里,其实还有一些其他的命令,参考如下链接

参考链接

https://docs.docker.com/engine/reference/builder/

猜你喜欢

转载自blog.csdn.net/wucong60/article/details/83414229