Docker 镜像构建之 Dockerfile

在 Docker 中构建镜像最常用的方式,就是使用 Dockerfile。Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。官方文档:https://docs.docker.com/engine/reference/builder/

引入部分

  1. 什么是 Dockerfile?

    • Dockerfile 是用来构建 Docker 镜像的构建文件, 是由一系列的命令和参数构成的脚本

    • 通过指令的方式构建镜像

  2. Dockerfile 主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令。

  3. 构建Dockerfile步骤

    1. 编写 Dockerfile 文件

    2. docker built 构建镜像

    3. docker run 创建容器

  4. Dockfile 文件的注意事项

    • Docker 以从上到下的顺序运行 Dockerfile 的指令。为了指定基本映像,第一条指令必须是 FROM。

    • 每条保留字指令都必须是大写字母, 并且后面要跟随至少一个参数

    • 指令按照从上到下的顺序执行

    • 每条指令可用 # 添加注释

    • 每条指令都会创建一个新镜像层, 并对镜像进行提交

  5. dockerfile的保留字指令

    • 主要保留指令:

      1. FROM

      2. RUN

      3. ADD

      4. COPY

      5. WORKDIR

      6. CMD

    一般用以上保留字指令就可以完成容器想要的功能,所有字段如下。

指令含义
FROM指定基础镜像,必须为第一个命令
MAINTAINER维护者信息
RUN构建镜像docker build时执行的命令
ADD将本地文件添加到容器中,tar 类型文件会自动解压(网络压缩资源不会被解压)
COPY功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
CMD在docker run时会执行的命令,如果存在多个则仅最后一个生效。
LABEL用于为镜像添加元数据
ENV设置环境变量
EXPOSE指定于外界交互的端口
VOLUME用于指定持久化目录
WORKDIR工作目录,类似于cd命令
ARG用于指定传递给构建运行时的变量
ONBUILD用于设置镜像触发器

二、Dockerfile 的保留字指令详解

1.FROM

  • 基础(依赖)镜像, 就是当前要创建的镜像是基于那个镜像

  • 基本语法如下:

FROM <image> 
FROM <image>:<tag> 
FROM <image>@<digest> 
示例: 
    FROM mysql:5.6 
# 注: tag 或 digest 是可选的,如果不使用这两个值时,会使用 latest 版本的基础镜像如果不以任何镜像为基础,那么写法为:FROM scratch。官方说明:scratch 镜像是一个空镜像,可以用于构建 busybox 等超小镜像,可以说是真正的从零开始构建属于自己的镜像。

2.MAINTAINER

  • 指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用 LABEL。

格式:
    MAINTAINER <name>
示例:
    MAINTAINER Jasper Xu MAINTAINER sorex@163.com
    MAINTAINER Jasper Xu <sorex@163.com>

3.LABEL

  • 语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...

  • 功能是为镜像指定标签或为镜像添加元数据。也可以使用 LABEL 来指定镜像作者。

?示例:元数据
LABEL version="1.0" description="这是一个 Web 服务器" by="IT 笔录"?注:使用 "LABEL" 指定元数据时,一条 "LABEL" 指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条 "LABEL" 指令指定,以免生成过多的中间镜像LABEL 
示例二 
maintainer="http://blog.taoxiaoxin.club/"

4.RUN

  • 容器构建时需要运行的命令

# RUN 用于在镜像容器中执行命令,一个Dockerfile文件内可以有多个RUN其有以下两种命令执行方式: 
shell 执行 
    格式:RUN <command> 
exec 执行 
    格式:RUN ["executable", "param1", "param2"] 
    示例:
         RUN ["executable", "param1", "param2"] 
         RUN apk update RUN ["/etc/execfile", "arg1", "arg1"] 
注: RUN 指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建 时指定--no-cache 参数,如:docker build --no-cache

5.EXPOSE

  • 暴露容器运行时的监听端口给外部,可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP。

?格式:
EXPOSE <port> [<port>...]
?示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp?注:"EXPOSE" 并不会让容器的端口访问到主机。如果想使得容器与宿主机的端口有映射关系,要使其可访问,需要在" docker run" 运行容器时通过"-p" 来发布这些端口,或通过"-P" 参数来发布" EXPOSE" 导出的所有端口,
​

6.WORKDIR

  • 指定创建容器后, 终端默认处在的工作目录, 也就是落脚点,为 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 设置工作目录。

?格式:
WORKDIR /path/to/workdir
?示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
​
?注:通过 "WORKDIR" 设置工作目录后,"Dockerfile" 中其后的命令 RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用 "docker run" 运行容器时,可以通过"-w" 参数覆盖构建时所设置的工作目录

7.ENV

  • 用来在构建镜像过程中设置环境变量

?格式:
ENV <key> <value> 
#<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... 
#可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
?示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy

8.ADD

  • 将宿主机目录下的文件拷贝到镜像里面 (会自动解压 tar 压缩包),src 可以是一个本地文件或者是一个本地压缩文件,压缩文件会自动解压。还可以是一个 url,如果把 src 写成一个 url,那么 ADD 就类似于 wget 命令,然后自动下载和解压。

?格式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]  # 用于支持包含空格的路径
?示例:
ADD hom* /mydir/            # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/        # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/       # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/      # 添加 "test" 到 /absoluteDir/

9.COPY

  • 类似 ADD, 拷贝本地文件到镜像中 (不会自动解压)

指令:COPY
功能描述:复制文件到镜像中。
语法:COPY < src> < dest>|[< src>, < dest>]
提示:指令逻辑和 ADD 十分相似,同样 Docker Daemon 会从编译目录寻找文件或目录,dest 为镜像中的绝对路径或者相对于 WORKDIR 的路径。

10.VOLUME

  • 用于目录挂载

?格式:
VOLUME ["/path/to/dir"]
?示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
​
?注:一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1. 卷可以容器间共享和重用
2. 容器并不一定要和其它容器共享卷
3. 修改卷后会立即生效
4. 对卷的修改不会对镜像产生影响
5. 卷会一直存在,直到没有任何容器在使用它

11.CMD (这个指令需放在最后)

  • 指定容器启动时要运行的命令

?格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了 ENTRYPOINT,则直接调用 ENTRYPOINT 添加参数)
CMD command param1 param2 (执行 shell 内部命令)
?示例:
CMD echo "This is a test." | wc -w
CMD ["/usr/bin/wc","--help"]
​
?注: "CMD" 不同于 "RUN""CMD" 用于指定在容器启动时所要执行的命令,而 "RUN" 用于指定镜像构建时所要执行的命令

12.ONBUILD

  • 用于设置镜像触发器

?格式:
ONBUILD [INSTRUCTION]
?示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src?注:当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被触发

三、构建镜像

Dockerfile 文件编写好以后,真正构建镜像时需要通过 docker build 命令。

  docker build 命令用于使用 Dockerfile 创建镜像。

# 使用当前目录的 Dockerfile 创建镜像
docker build -t mycentos:7 .
# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .
​
  • -f:指定要使用的 Dockerfile 路径;

  • --tag, -t:镜像的名字及标签,可以在一次构建中为一个镜像设置多个标签。

关于 . 理解

 我们在使用 docker build 命令去构建镜像时,往往会看到命令最后会有一个 . 号。它究竟是什么意思呢?

  很多人以为是用来指定 Dockerfile 文件所在的位置的,但其实 -f 参数才是用来指定 Dockerfile 的路径的,那么 . 号究竟是用来做什么的呢?

  Docker 在运行时分为 Docker 引擎(服务端守护进程)客户端工具,我们日常使用各种 docker 命令,其实就是在使用 客户端工具Docker 引擎 进行交互。

  当我们使用 docker build 命令来构建镜像时,这个构建过程其实是在 Docker 引擎 中完成的,而不是在本机环境。如果在 Dockerfile 中使用了一些 ADD 等指令来操作文件,如何让 Docker 引擎 获取到这些文件呢?

  这里就有了一个 镜像构建上下文 的概念,当构建的时候,由用户指定构建镜像时的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到上下文中的文件了。

  举个栗子:我的宿主机 jdk 文件在 /root 目录下,Dockerfile 文件在 /usr/local/dockerfile 目录下,文件内容如下:

ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

那么构建镜像时的命令就该这样写:

docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root

再举个栗子:我的宿主机 jdk 文件和 Dockerfile 文件都在 /usr/local/dockerfile 目录下,文件内容如下:

ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

 那么构建镜像时的命令则这样写:

docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .
​

四、Dockerfile实践

接下来我们通过基础镜像 centos:7,在该镜像中安装 jdk 和 tomcat 以后将其制作为一个新的镜像 mycentos:7

  创建目录。

mkdir -p /usr/local/dockerfile

  编写 Dockerfile 文件。

vi Dockerfile

  Dockerfile 文件内容如下:

# 指明构建的新镜像是来自于 centos:7 基础镜像
FROM centos:7
# 通过镜像标签声明了作者信息
LABEL maintainer="mrhelloworld.com"
# 设置工作目录
WORKDIR /usr/local
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷贝文件到镜像中并解压
ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
ENV PATH $PATH:$JAVA_HOME/bin
# 启动容器时启动 tomcat
CMD ["/usr/local/tomcat/apache-tomcat-9.0.37/bin/catalina.sh", "run"]

 构建镜像。

[root@localhost ~]# docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root/
Sending build context to Docker daemon  191.4MB
Step 1/10 : FROM centos:7
 ---> 7e6257c9f8d8
Step 2/10 : LABEL maintainer="mrhelloworld.com"
 ---> Running in 3f18aa4f3fb2
Removing intermediate container 3f18aa4f3fb2
 ---> 7364f68ca4ab
Step 3/10 : WORKDIR /usr/local
 ---> Running in d9889152cfc4
Removing intermediate container d9889152cfc4
 ---> d05bd2e09fa4
Step 4/10 : RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
 ---> Running in 3bcd6ef78350
Removing intermediate container 3bcd6ef78350
 ---> 4832abf9d769
Step 5/10 : ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
 ---> e61474bf7a76
Step 6/10 : ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat
 ---> 7110cdff7438
Step 7/10 : EXPOSE 8080
 ---> Running in a4731c1cf77d
Removing intermediate container a4731c1cf77d
 ---> f893cefee00c
Step 8/10 : ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
 ---> Running in f0cb08f390db
Removing intermediate container f0cb08f390db
 ---> ff9f6acf6844
Step 9/10 : ENV PATH $PATH:$JAVA_HOME/bin
 ---> Running in eae88cf841d0
Removing intermediate container eae88cf841d0
 ---> 4b9226a23b10
Step 10/10 : CMD ["/usr/local/tomcat/apache-tomcat-9.0.37/bin/catalina.sh", "run"]
 ---> Running in ccf481045906
Removing intermediate container ccf481045906
 ---> 9ef76a16441b
Successfully built 9ef76a16441b
Successfully tagged mycentos:7

五、镜像构建历史

docker history 镜像名称:标签|ID
docker history mycentos:7

image-20201211112054179

六、使用构建的镜像创建容器

# 创建容器
docker run -di --name mycentos7 -p 8080:8080 mycentos:7
# 进入容器
docker exec -it mycentos7 /bin/bash
# 测试 java 环境变量
[root@dcae87df010b /]# java -version
java version "11.0.6" 2020-01-14 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.6+8-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.6+8-LTS, mixed mode)
# 访问 http://192.168.10.10:8080/ 看到页面说明环境 OK!

image-20201211112019626

七、Dockerfile 训练

1.使用 centos7 作为基础镜像部署 nginx 服务

  • 先创建一个 nginx.repo 文件

# vim nginx.repo
'''文件内容
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
'''
  • 编写 Dockerfile 文件

[root@shawn ~]# vim Dockerfile

# 指定基础镜像(依赖镜像)
FROM centos:7

# 执行一个命令
RUN yum install -y yum-utils

# 将本地文件添加到容器中
ADD nginx.repo /etc/yum.repos.d/nginx.repo

# 更新YUM缓存
RUN yum makecache

# 安装nginx
RUN yum install -y nginx

# 制定容器启动默认执行的命令
CMD nginx -g 'daemon off;'
  • 构建镜像

[root@shawn ~]# docker build -t install/nginx:v1 .
  • 查看刚刚构建的镜像, 然后实例容器

[root@shawn ~]# docker images
[root@shawn ~]# docker run -dit install/nginx:v1 sh
  • 查看刚刚实例出的容器, 并进入到容器中

[root@shawn ~]# docker exec -it 94f8e35f3357  bash
  • 检测 nginx 是否部署成功

[root@shawn ~]# crul 127.0.0.1  # 出现 html 代码说明部署成功

2.在容器中编译安装 nginx 服务

  • 编辑 Dockerfile 文件

[root@shawn ~]# vim Dockerfile
'''文件内容
# 指定基础镜像(依赖镜像)
FROM centos:7

# 执行命令
RUN yum install yum-utils wget zlib zlib-devel pcre pcre-devel make gcc gcc-c++
RUN cd /opt && wget http://nginx.org/download/nginx-1.18.0.tar.gz && tar -xvf nginx.1.18.0/ && cd nginx-1.18.0/ && ./configure && make && make install

# 指定进入容器的默认工作目录
WORKDIR /usr/local/nginx/sbin

# 指定容器启动默认执行的命令
CMD ./nginx -g 'daemon off;'
'''
  • 构建镜像

[root@shawn ~]# docker build -t yuan/install/nginx:v2 .
  • 查看是否构建成功,并实例出容器

[root@shawn ~]# docker images
[root@shawn ~]# docker run -dit --name yuan_nginx yuan/install/nginx:v2 sh
  • 查看容器是否启动成功, 并测试 nginx

[root@shawn ~]# docker exec yuan_nginx crul 127.0.0.1  # 出现 html 代码说明部署成功

3.构建以 Centos 为依赖镜像并安装 Django 的服务

  • 首先构建一个Dockerfile文件

[root@shawn ~]#vim Dockerfile
# 指定基础镜像
FROM centos:7
# 运行命令
RUN yum makecache && yum update -y && yum install -y python3 && pip3 install django
# 拷贝本地文件到容器
COPY shawn /root/
# 指定进入到容器的工作目录
WORKDIR /root/
# 指定向外暴露的端口
EXPOSE 8080
# 运行命令
CMD cd ./shawn && python3 manage.py runserver 0.0.0.0:8080
  • 文件 shawn 的构建

在宿主机上安装 Django
django-admin startproject shawn  #创建一个 "Shawn" 项目
cd ./shawn  #进入目录
django-admin startapp application  #开始项目
cd ./shawn
vim setting.cong  #修改配置文件"*"代理
cd .. #退出
  • 构建镜像

[root@shawn ~]#docker build -t test333:v1 .
  • 查看并使用镜像实例化出容器

[root@shawn ~]#docker images
[root@shawn ~]#docker run -dit --name test001 -p 9999:8080 test333:v1 sh
  • 查看刚开启的容器,并进入容器启动 Django 服务

[root@shawn ~]#docker exec -it test001 bash
[root@80f1315c030c ~]# python3 manage.py runserver 0.0.0.0:8080
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
December 04, 2020 - 06:50:19
Django version 3.1.4, using settings 'lingxiu.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.
  • 使用浏览器验证一下

image-20201204180450328

3.构建以 python 为依赖镜像并安装 Django 服务

  • 编辑 Dockerfile 文件

[root@shawn ~]# vim Dockerfile
'''文件内容
# 指定依赖镜像
FROM python:3.6# 设置作者
MAINTAINER Shawn# 执行命令
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip3 install django==2.2.2# 拷贝文件
COPY app /root/# 设置工作目录
WORKDIR /root/# 执行命令
CMD cd ./app && python3 manage.py runserver 0.0.0.0:7777
  • 文件 app 的构建

在宿主机上安装 Django
django-admin startproject app  #创建一个 "app" 项目
cd ./app  #进入目录
django-admin startapp application  #开始项目
cd ./app
vim setting.cong  #修改配置文件"*"代理
cd .. #退出
  • 构建镜像

[root@shawn ~]#docker build -t jjjj .
  • 查看并使用镜像实例化出容器

[root@shawn ~]#docker images
[root@shawn ~]#docker run -dit --name jjjjtest -p 4444:7777 jjjj:latest sh
  • 查看刚开启的容器,并进入容器启动 Django 服务

[root@shawn ~]#docker exec -it jjjtest bash
root@b85f93fcc114:~# python3 manage.py runserver 0.0.0.0:7777
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
December 04, 2020 - 10:17:51
Django version 2.2.2, using settings 'app.settings'
Starting development server at http://0.0.0.0:7777/
Quit the server with CONTROL-C.
  • 使用浏览器检验一下

image-20201204182344217

4.使用 NGINX 代理 Django

  • 先构建一个 Django 服务, 步骤与上一个例子相同

  • 改变了一下向外暴露的端口

?编写 "Dockerfile" 文件
[root@shawn DjangoDocker]#vim Dockerfile 
'''文件内容
# 指定依赖镜像
FROM pyhton:3.6

# 安装 Django
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip3 install django==2.2.2

# COPY 文件
COPY app /root/

# 指定工作目录
WORKDIR /root/

# 运行命令
CMD cd ./app && python3 manage.py runserver 0.0.0.0:8080
'''
[root@shawn DjangoDocker]#ls
app  Dockerfile  # 这两个文件, "app" 在上一个例子中有构建

?构建镜像,并查看
[root@shawn DjangoDocker]#docker build -t python_django:v6 .
[root@shawn DjangoDocker]#docker images

?实例出容器,并查看
[root@shawn DjangoDocker]#docker run -dit --name p_d_test1 -p 8888:8080 python_django:v6 sh
6906ff9e3ec0f9d583eb27890d82c79deff4358a43e5f1ec768a702547d020bf
[root@shawn DjangoDocker]#docker ps

?进到容器里面,开启服务,再测试
[root@shawn DjangoDocker]#docker exec -it p_d_test1 bash
root@6906ff9e3ec0:~# python3 manage.py runserver 0.0.0.0:8080
[root@shawn DjangoDocker]#curl 127.0.0.1:8888
  • 然后来编写 nginx 服务以及代理配置

?编写 "nginx.repo" 文件
[root@shawn NginxDocker]#vim nginx.repo
'''文件内容(官网可复制)
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
'''

?编写 "default.conf" 文件(代理"Django"配置)
[root@shawn NginxDocker]#vim default.conf
'''文件内容
server {
        listen 80;
        server_name www.py16zxl.com;

        location / {
        # 这里填的是 Django 服务的访问地址与端口(映射端口)
        proxy_pass http://192.168.13.234:8888/;
        index index.html index.htm index.jsp;
        }
}
'''

?编写 "Dockerfile" 文件
[root@shawn NginxDocker]#vim Dockerfile
'''文件内容
# 指定依赖进行
FROM centos:7

# 指定作者
MAINTAINER shawn

# 安装依赖
RUN yum install -y yum-utils gcc gcc-c++ pcre pcre-devel zlib zlib-devel make wget

## 源码安装 nginx1.18.0
# RUN wget http://nginx.org/download/nginx-1.18.0.tar.gz && tar -xvf nginx-1.18.0.tar.gz && cd nginx.1.18.0 && ./configure --prefix="/usr/local/nginx-1.18.0" && make && make install

# 拷贝 NGINX 配置文件
COPY nginx.repo /etc/yum.repos.d/

# 更新 yum 软件包索引
RUN yum makecache fast

# yum 安装 nginx
RUN yum install -y nginx

# 指定向外暴露的端口
EXPOSE 8000

# 拷贝 nginx 默认配置文件
COPY default.conf /etc/nginx/conf.d/

# 容器起来运行的命令
CMD /usr/local/nginx-1.18.0/sbin/nginx -g 'daemon off;' 
'''

?当前需要的文件
[root@shawn NginxDocker]#ls
default.conf  Dockerfile  nginx.repo

?开始构建镜像,并查看
[root@shawn NginxDocker]#docker build -t nginx_d:v7 .
[root@shawn NginxDocker]#docker images

?实例化出容器,并查看
[root@shawn NginxDocker]#docker run -dit --name nginx_d -p 80:80 nginx_d:v7 sh
[root@shawn NginxDocker]#docker ps

?进入容器,开启 "nginx" 服务,并验证
[root@shawn NginxDocker]#docker exec -it nginx_d bash
[root@51f54c1d5abb /]#nginx
[root@shawn NginxDocker]#curl 127.0.0.1:80
# 发现通过访问 nginx 也可以进入 Django 页面

image-20201205180845116