Docker Dockerfile的教程和构建图像的示例

时间:2020-03-05 15:25:17  来源:igfitidea点击:

目前的文章将在Dockerfile中行走Docker Ecosystem中最使用的概念之一。
我们将探索DockerFile的构建块,以自动构建Docker图像的应用程序和服务。

Dockerfile基本上是一个文本文件,包含一组指令或者命令瞄准Docker图像。
因此,调用Docker Build命令Docker读取Dockerfile的指令并捆绑Docker镜像。

我们将学到什么

  • dockerfile指令
  • 构建Docker图像的例子

文章的结构安排如下

  • dockerfile使用
  • Dockerfile结构和常用说明
  • dockerfile例子
  • 结论

dockerfile使用

主要是,构建Docker图像的命令如上所述Docker构建${上下文}; ${context}是我们的图像的上下文,它可以是主机文件系统中的文件夹的路径或者Git存储库的URL;粗略地介绍${上下文}是在构建阶段期间dockerfile所需的所有文件。

构建由Docker守护程序运行而不是Docker CLI。
所有${context}递归地向Docker守护程序发送,因此,强烈建议使用"/"作为图像上下文的路径,因为将发送到"/"的所有内容。
dockerfile必须位于${context}的根目录中。

Docker允许使用。
Dockerignore文件指定必须从构建中排除的所有文件和文件夹,因此,它们不会被发送到Docker守护程序,并通过这样做发送,因此我们将增加建筑物性能。

让我们创建一个简单的dockerfile,只包含一个指令,我稍后会解释:

>>  docker-dockerfile cat Dockerfile
FROM node:latest

从此DockerFile构建Docker的最简单方法是运行Docker构建并将当前目录作为${上下文}:

>>  docker-dockerfile docker build .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM node:latest
---> 36dc1bb7a52b
Successfully built 36dc1bb7a52b

可以通过添加-F参数来指定Dockerfile的路径:

>>  Code docker build -f docker-dockerfile/Dockerfile docker-dockerfile/

Docker Image Building最重要的特征之一是能够标记我们的图像,以便我们可以通过标签(主要是名称)找到它们。
因此,要标记图像,我们必须添加Argument -T和标记名称;我们还可以通过添加-t ${tag_name}:${version}分配图像的版本

>>  docker-dockerfile docker build -t theitroad/nodejs .
>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.1 .

我们可以检查内置图像是否:

>>  docker-dockerfile docker images theitroad/nodejs
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
theitroad/nodejs     0.0.1               36dc1bb7a52b        2 weeks ago         655.5 MB
theitroad/nodejs     latest              36dc1bb7a52b        2 weeks ago         655.5 MB

dockerfile结构

dockerfile的格式/结构非常简单,这基本上如下:

# Comment goes here
INSTRUCTION argument1 argument2 argument3 …

指令是非区分大小写的,但由于会议开发人员使用以大写格式编写指令。
dockerfile中指令的顺序很重要,这是相同的次数遵循图像构建时间。

.dockerignore文件

以下是一个例子。
Dockeringore文件,说明所有何种形式允许从Docker Image构建中排除文件或者文件夹:

>>  docker-dockerfile cat .dockerignore
# this is a comment
*/temp*
*/*/temp*
temp?
node_modules/
.git/
  • */temp *:排除名称以temp开头的所有文件或者目录,并且是根的子目录,例如of the root,例如of the root,fearte_folder/temp.txt/parent_folder/tempo /等。
  • //temp *:与第一个相同,但root是两个级别
  • temp?:涉及临时像速度等一个字符的文件或者目录。
  • node_modules /:从build中排除文件夹node_modules /在当前文件夹中。
  • .git /:排除隐藏文件夹.git /在build的当前文件夹中。

从以来开始的所有行都被视为注释,因此它们在构建时被忽略。

Dockerfile结构和常用说明

1)FROM

从指令设置后续指令的基础图像设置。
基本上,有效的Dockerfile必须在没有考虑注释的情况下从指令中获得的第一行。
Docker守护程序将首先检查图像是否存在于主机中,否则将从Docker Hub中拉出来。
该指令有三种形式:

FROM <image>
FROM <image:tag>
FROM <image><@digest>

从:

  • 必须是第一个非注释行
  • 可以在同一个dockerfile中看起来多次
  • <image> @ <digest>和<tag>是可选的,如果指定的Docker将拉动确切的图像,否则它将拉动最新图像。

在我们的第一个例子中(见上文)我们使用nodejs镜像使用: FROM node:latest

2)MAINTAINER

此指令允许我们指定内置镜像的作者;例如

MAINTAINER <name>

# Example 2:
FROM node:latest
MAINTAINER theitroad

3)RUN

该指令旨在执行命令。
该命令将在图像顶部的新图层中执行并提交结果,该结果将用作下一个指令的图像等。
运行有两个表单,shell表单和exec:

RUN <command> : shell格式,该命令在shell中运行,默认/bin/sh -c for linux或者cmd/s/c for windows。
RUN [“executable", “argument1", “argument2", “argument3" …]

将Run命令添加到我们的dockerfile示例中:

# Example 1
# ---------
FROM node:latest
# Example 2
# ---------
MAINTAINER theitroad
# Example 3
# ---------
RUN /bin/sh -c 'echo "*** hello Dockerfile!! ***"'
RUN ["npm", "--version"]

让我们构建图像以查看此示例在操作中,请注意该命令的"echo"*** hello dockerfile !! ***"和npm -version已被执行。

>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.3 .
…
Step 3 : RUN /bin/sh -c 'echo "*** hello Dockerfile!! ***"'
 ---> Running in 6ebdd85f7687
*** hello Dockerfile!! ***
…
Step 4 : RUN npm --version
 ---> Running in bc9dbc7cf8c1
3.10.10
…

4)标签

此指令将Metadata添加到图像中作为键值对。
格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

  • 我们可以使用多行标签:
LABEL "com.example.image "="Node Js image LABEL example"

LABEL version="0.0.4"

LABEL description=" label-values \

can span multiple lines."
  • 我们可以使用具有多个键值对的一行标签:
LABEL "com.example.image"="Node Js image LABEL example" version="0.0.4" description=" label-values \

can span multiple lines."

让我们构建图像:

>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.3 . --no-cache=true

检查镜像:

>>  docker-dockerfile docker inspect theitroad/nodejs:0.0.3
…
"Labels": {
                "com.example.image": "Node Js image LABEL example",
                "description": " label-values can span multiple lines.",
                "version": "0.0.4"
            }
…

5)EXPOSE

EXPOSE <port> [<port>...]

此指令通知Docker Container在运行时在指定的网络端口上侦听。
它不会使主机可访问的容器的端口。
为此,必须使用-p标志来发布一系列端口或者-p标志,以发布所有公开的端口。

# Example 1
# ---------
FROM node:latest
# Example 2
…
# Example 5
# ---------
EXPOSE 3000

6)ENV.

按照与标签相同的格式,但要定义环境变量。

…
# Example 6
# ---------
ENV mysql_root_password test dsf
ENV src_folder ./src/app

构建图像并检查它以检查env变量:

>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.3 . --no-cache=true
>>  docker-dockerfile docker inspect theitroad/nodejs:0.0.3
…
"Env": [             "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NPM_CONFIG_LOGLEVEL=info",
                "NODE_VERSION=7.2.1",
                "mysql_root_password=test  dsf",
                "src_folder=./src/app"
            ]
…

7)ADD

此指令从<src>复制新文件,目录或者远程文件URL,并将其添加到PATH <DEST>的图像的文件系统。
格式是:

ADD <src>... <dest> but if the paths containing whitespace we need to use ADD ["<src>",... "<dest>"]

...
# Example 7
# ---------
ADD . /src/app/

此示例将当前目录内容复制到图像中的/src/app /中。

  • 如果<dest>不以尾随斜杠结束,则将被视为常规文件,并且<src>的内容将写在<dest>。
  • 如果<dest>不存在,则它将与其路径中的所有缺少目录一起创建。
  • 在<SRC>路径中允许基本通配符,Dist * Readm?.txt等。

如果<src>是存档(tar,gzip,bzip2或者xz)添加将自动解压缩<dest>

8)COPY

这条指令非常类似于添加和几乎做同样的事情。
复制与添加具有相同的表单,它将文件/目录复制到<src>进入<dest>。
实际上,与添加不同,副本不会除URL作为<SRC>,它不会解压缩归档<SRC>文件。

9)ENTRYPOINT

此命令允许我们指定启动命令,该命令将始终在容器启动时执行。

...
# Example 8
# ---------
ENTRYPOINT  ["/bin/echo", "Hello theitroad"]

重建Docker图片:

>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.3 . --no-cache=true

从内置图像运行一个容器:

>>  docker-dockerfile docker run -it --name nodejs-dockerfile theitroad/nodejs:0.0.3
Hello theitroad

请注意,只允许使用dockerfile的一个入口点。

10)cmd.

命令cmd几乎与命令ententpoint相似,也是dockerfile允许的一个命令。
入口点和CMD之间的主要区别在于,一旦在Docker运行中指定了命令,省略了CMD ...

...
# Example 8
# ---------
ENTRYPOINT  ["/bin/echo", "Hello theitroad"]
# Example 9
# ---------
CMD  ["Yo World!!"]

重建图像:

>>  docker-dockerfile docker build -t theitroad/nodejs:0.0.3 . --no-cache=true

创建一个Docker容器

>>  docker-dockerfile docker run -it --name nodejs-dockerfile theitroad/nodejs:0.0.3
Hello theitroad Yo World!!

通过在Docker运行结束时添加命令来创建第二个容器,因此,CMD将省略:

>>  docker-dockerfile docker run -it --name nodejs-dockerfile2 theitroad/nodejs:0.0.3 Horay
Hello theitroad Horay

11)VOLUME

卷令创建具有指定名称的挂载点,并将其标记为从本机主机或者其他容器中持有外部安装卷。

# Example 10
# ---------
VOLUME  /var/log

12)USER

USER <daemon or UID>

用户指令设置在运行图像时使用用户名或者UID,并用于任何运行,CMD和EntryPoint指令。

# Example 11
# ---------
USER  deep

13)Workdir.

Workdir/path/to /文件夹

该指令为Dockerfile中的任何运行,CMD,EntryPoint,复制和添加说明设置了工作目录。
如果Workdir不存在,则将创建该文件夹以及父文件夹。
我们可以理解Workdir作为Linux的CD'命令,除了将创建文件夹,不存在。

dockerfile例子

请参阅每个DockerFile示例中的注释。

nodejs app dockerfile示例:

FROM node:argon
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]

nginx dockerfile示例:

FROM debian:jessie
MAINTAINER NGINX Docker Maintainers "[email protected]"
ENV NGINX_VERSION 1.11.7-1~jessie
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
     && echo "deb http://nginx.org/packages/mainline/debian/jessie nginx" >> /etc/apt/sources.list \
     && apt-get update \
     && apt-get install --no-install-recommends --no-install-suggests -y \
                               ca-certificates \
                               nginx=${NGINX_VERSION} \
                               nginx-module-xslt \
                               nginx-module-geoip \
                               nginx-module-image-filter \
                               nginx-module-perl \
                               nginx-module-njs \
                               gettext-base \
     && rm -rf /var/lib/apt/lists/*
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
     && ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD [ "nginx", "-g", "daemon off;" ]