没有输出的输入是不完整的

0%

Docker进阶-Dockerfile的编写和使用

在实际开发中完全使用他人构造好的镜像是不现实的。
所以本篇文章我们将会学习Dockerfile的知识,从而学习如何构造符合项目要求的镜像。

Dockerfile文档展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FROM ubuntu:16.04

RUN apt-get update -y && \
apt-get install -y python3-pip python3-dev

# We copy just the requirements.txt first to leverage Docker cache
COPY ./requirements.txt /app/requirements.txt

WORKDIR /app

RUN python3 -m pip install --upgrade pip
RUN pip3 install -r requirements.txt

COPY . /app

# ENTRYPOINT [ "python3" ]

CMD [ "python3", "main.py" ]

逐行命令解释

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1. FROM ubuntu:16.04

FROM 关键字会初始化一个image构造,并为后续的所有操作设置基础镜像,,上面的例子表示,该image是以ubuntu:16.04为基础构建的。


2. RUN apt-get update -y && \
apt-get install -y python3-pip python3-dev

RUN 会在上一层的基础上添加新的layer,并将结果提交给下一层。RUN命令有两种形式。一种是shell格式,格式如下
RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)

另一种是exec格式,格式如下
RUN ["executable", "param1", "param2"] (exec form)

&& \ 并不是Docker独有的,只是告诉linux这两条命令要一起执行,而不是执行两次,这样就只会产生一层layer,如果有两个RUN,那么就会产生两个中间层。

3. COPY ./requirements.txt /app/requirements.txt
COPY 命令同样有两种形式,可以实现将源文件复制到目标位置,支持正则表达式。
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

4. WORKDIR /app
- WORKDIR 会设置当前的工作目录,在本条指令之后的RUN, CMD, ENTRYPOINT, COPY 和 ADD目录都是在当前目录下执行的。
- WORKDIR 可以出现多次,从而更换shell的执行路径

5. RUN python3 -m pip install --upgrade pip
6. RUN pip3 install -r requirements.txt
RUN命令的shell形式,更新pip同时安装依赖。

7. COPY . /app
复制命令 将当前目录的所有文件复制到/app目录下

8.CMD [ "python3", "main.py" ]
CMD的作用是提供容器的默认指令,也就是我们docker run 的最后一个参数。CMD有三种形式,在一个Dockerfile中,如果有多个CMD指令,那么只有最后一个CMD命令会起作用。
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)

如果CMD命令后只有参数,没有可执行的命令,那么它肯定是配合ENTRYPOINT使用的。同时要注意,如果是配合ENTRYPOINT的时候,CMD和ENTRYPOINT都要使用使用 JSON array 格式。如果用ENTRYPOINT进行改写,则如下所示。

ENTRYPOINT [ "python" ]
CMD [ "main.py" ]

打包镜像

1
2
3
docker build -t kuakua:latest .
-t 设置镜像名称和标签,如果标签没有设定,默认是latest
. 在当前目录寻找Dockerfile进行镜像打包。

运行容器

1
2
3
4
5
6
7
8
 docker run -d -p 5001:5000 --name kuakua -v /Users/liqingwen/workplace/temp/kuakua/log:/log kuakua:latest

// 详细解释
-d 表示以守护进程的形式进行执行,后台运行
-p 5001:5000 将容器的5000端口映射到宿主机的5001端口
--name kuakua 将当前容器命名为kuakua
-v bind mount a volumn 将容器的log目录和本地的/Users/liqingwen/workplace/temp/kuakua/log做一个映射。如果容器端log目录下有内容更新,则本地的log目录也会同步更新。
kuakua:latest 镜像名称

项目地址

本项目完整代码已经在github开源,项目地址夸夸机器人,欢迎大家去尝试一下。

参考

  1. dockerfile 官方参考文档
  2. Dockerize your Flask Application