Docker 之 Dockerfile

Dockerfile 介绍

Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile 从 FROM 命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。

Dockerfile 语法

Dockerfile语法由两部分构成,注释命令 + 参数

1
2
# Line blocks used for commenting
command argument argument ..

一个简单的例子:

1
2
# Print "Hello docker!"
RUN echo "Hello docker!"

Dockerfile 命令

Dockerfile 有十几条命令可用于构建镜像,下文将简略介绍这些命令。

FROM

FROM 命令可能是最重要的 Dockerfile 命令。该命令定义了使用哪个基础镜像启动构建流程。基础镜像可以为任意镜像。如果基础镜像没有被发现,Docker 将试图从 Docker image index 来查找该镜像。FROM 命令必须是Dockerfile 的首个命令。

1
2
# Usage: FROM [image name]
FROM nginx:alpine

env

ENV 命令用于设置环境变量。这些变量以 key=value 的形式存在,并可以在容器内被脚本或者程序调用。这个机制给在容器中运行应用带来了极大的便利。

1
2
# Usage: ENV key value
ENV SERVER_WORKS 4

ADD

ADD 命令有两个参数,源和目标。它的基本作用是从源系统的文件系统上复制文件到目标容器的文件系统。如果源是一个 URL,那该 URL 的内容将被下载并复制到容器中。

1
2
# Usage: ADD [source directory or URL] [destination directory]
ADD /my_app_folder /destination_folder
  1. 如果源路径是个文件,且目标路径是以 / 结尾, 则 Docker 会把目标路径当作一个目录,会把源文件拷贝到该目录下。如果目标路径不存在,则会自动创建目标路径。
  2. 如果源路径是个文件,且目标路径是不是以 / 结尾,则 Docker 会把目标路径当作一个文件。如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件;如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。
  3. 如果源路径是个目录,且目标路径不存在,则 Docker 会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。如果目标路径是个已经存在的目录,则 Docker 会把源路径目录下的文件拷贝到该目录下。
  4. 如果源文件是个归档文件(压缩文件),则 Docker 会自动帮解压。

copy

COPY 指令和 ADD 指令功能和使用方式类似。只是 COPY 指令不会做自动解压工作。

RUN

RUN 命令是 Dockerfile 执行命令的核心部分。它接受命令作为参数并用于创建镜像。不像 CMD 命令,RUN 命令用于创建镜像(在之前 commit 的层之上形成新的层)。

1
2
# Usage: RUN [command]
RUN npm install

CMD

RUN 命令相似,CMD 可以用于执行特定的命令。和 RUN 不同的是,这些命令不是在镜像构建的过程中执行的,而是在用镜像构建容器后被调用。只能有一个 CMD 指令,如果有多个 CMD 指令则以最后一个为准。

1
2
# Usage 1: CMD application "argument", "argument", ..
CMD "echo" "Hello docker!"

ENTRYPOINT

配置容器启动后执行的命令,只有在执行 docker run 命令启动容器时才会起作用,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。ENTRYPOINT 帮助你配置一个容器使之可执行化,如果你结合 CMD 命令和 ENTRYPOINT 命令,你可以从 CMD 命令中移除 “application” 而仅仅保留参数,参数将传递给 ENTRYPOINT 命令。

1
2
3
4
5
6
7
8
9
# Usage: ENTRYPOINT application "argument", "argument", ..
# Remember: arguments are optional. They can be provided by CMD
# or during the creation of a container.
ENTRYPOINT echo

# Usage example with CMD:
# Arguments set with CMD can be overridden during *run*
CMD "Hello docker!"
ENTRYPOINT echo

EXPOSE

EXPOSE 用来指定端口,使容器内的应用可以通过端口和外界交互。

1
2
# Usage: EXPOSE [port]
EXPOSE 8080

USER

USER 命令用于设置运行容器的 UID。

1
2
# Usage: USER [UID]
USER 751

VOLUME

VOLUME 命令用于让你的容器访问宿主机上的目录。

1
2
# Usage: VOLUME ["/dir_1", "/dir_2" ..]
VOLUME ["/my_files"]

WORKDIR

WORKDIR 命令用于设置 CMD 指明的命令的运行目录。

1
2
# Usage: WORKDIR /path
WORKDIR ~/

完整 Dockerfile 示例

这是一个构建 Node.js 应用的 Dockerfile:

1
2
3
4
5
6
7
8
FROM node:8.9-alpine
ENV NODE_ENV production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"]
RUN npm install --production --silent && mv node_modules ../
COPY . .
EXPOSE 3000
CMD npm start

这是一个构建 Python 应用的 Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Python support can be specified down to the minor or micro version
# (e.g. 3.6 or 3.6.3).
# OS Support also exists for jessie & stretch (slim and full).
# See https://hub.docker.com/r/library/python/ for all supported Python
# tags from Docker Hub.
FROM python:alpine

# If you prefer miniconda:
#FROM continuumio/miniconda3

LABEL Name=hnsw_test Version=0.0.1
EXPOSE 3000

WORKDIR /app
ADD . /app

# Using pip:
RUN python3 -m pip install -r requirements.txt
CMD ["python3", "-m", "hnsw_test"]

# Using pipenv:
#RUN python3 -m pip install pipenv
#RUN pipenv install --ignore-pipfile
#CMD ["pipenv", "run", "python3", "-m", "hnsw_test"]

# Using miniconda (make sure to replace 'myenv' w/ your environment name):
#RUN conda env create -f environment.yml
#CMD /bin/bash -c "source activate myenv && python3 -m hnsw_test"

如何使用 Dockerfile

在 Dockerfile 文件的路径下运行(注意 . 不能忘记):

1
2
3
# Build an image using the Dockerfile at current location
# Example: sudo docker build -t [name] .
$ docker build -t docker-vue-alpine .

运行所构建的镜像:

1
$ docker run -p 88:80 -d docker-vue-alpine
0%