前文我们使用官方提供的hello world镜像作为验证例子,本文我们将基于Nginx+Ubuntu,根据我们的需求定制Docker镜像,并将其上传到DockerHub上,供以后多次使用。
0x01 准备文件
在开始构建镜像之前,我们首先看下构建一个基于Nginx+Ubuntu的Docker镜像,所需要的基本文件。文件目录结构,是按我的习惯布置的,读者可自行修改。如下文档可以访问Github仓库
sanxiansite/docker-images/docker-nginx-ubuntu
下载。

0x02 对文件 Dockefile 的说明
其中Dockerfile文件是构建镜像的核心文件,基于该文件,我们使用docker build命令来构建镜像。我们看下它的内容:
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
| # Nginx 服务镜像
# sudo docker build --build-arg VERSION=1.0.0 -t nginx-ubuntu:1.0.0 .
# sudo docker run -d -p 80:80 nginx-ubuntu:1.0.0
FROM ubuntu:22.04
WORKDIR /opt/app
LABEL maintainer="mancode@sohu.com"
# 定义环境变量
ENV NGINX_PACKAGE_PATH /opt/app/nginx
ENV NGINX_PATH /usr/local/nginx
COPY ./nginx/nginx-1.25.4.tar.gz ${NGINX_PACKAGE_PATH}/nginx-1.25.4.tar.gz
COPY ./nginx/docs/index.html ${NGINX_PATH}/www/index.html
RUN apt update && apt install -y gcc g++ make libssl-dev libpcre3 libpcre3-dev zlib1g-dev \
&& useradd -M -s /sbin/nologin nginx \
&& cd ${NGINX_PACKAGE_PATH} && tar -zxf nginx-1.25.4.tar.gz && cd nginx-1.25.4 \
&& ./configure \
--prefix=/usr/local/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_gzip_static_module \
--with-http_sub_module \
&& make && make install \
&& mkdir -p /var/log/nginx \
&& mkdir -p /var/cache/nginx
COPY ./nginx/conf/ /etc/nginx/
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off; master_process on;"]
|
这里简单描述下该文件的具体含义:
| No.1 ~ No.3 | 是注释行,这里我分别写了构建指令以及运行指令,供读者使用。 |
| No.5 | 我们特别注意,此命令表明我们使用名为“ubuntu:22.04”的Docker镜像作为基础镜像,来构建我们的镜像。 构建时,系统会从hub.docker.com自动下载到本地。 |
| No.7 | 镜像运行时默认的当前工作目录 |
| No.15 | 将本地的nginx源码包拷贝到镜像中:/opt/app/nginx/nginx-1.25.4.tar.gz。 |
| No.17 | 将本地的nginx静态页面拷贝到镜像:/usr/local/nginx/www/index.html。该文件作为测试nginx的默认静态页面。 |
| No.19 | 由于编译Nginx需要第三方库的支撑,使用apt安装在镜像中编译nginx所需要的第三方库。 |
| No.21 | 解压Nginx源代码包。 |
| No.22 ~ No.34 | 配置Nginx,从而产生Makefile文件。 |
| No.35 | 编译Nginx,并进行安装。 |
| No.36 | 创建镜像中nginx日志目录。 |
| No.37 | 创建镜像中nginx所需http-client-body-temp-path等临时目录。 |
| No.39 | 将本地nginx配置文件拷贝到镜像:/etc/nginx/nginx.conf、/etc/nginx/conf.d/default.conf。该配置文件将作为nginx容器的启动配置文件。 |
| No.41 | 指定容器的入口地址,作为第一个执行的程序,也是pid=1的进程。 |
注意
Nginx的镜像,务必在ENTRYPOINT的入口或者nginx.conf配置文件中 指定 daemon off 属性,表明不让Nginx自动进入后台守护进程。
如果不指定该属性,你会发现启动镜像,容器就会马上退出!
这是因为:Docker默认将容器内部的第一个进程,亦即pid=1的程序作为容器是否存活的判断条件,如果容器中pid=1的进程挂掉了,该容器便会自动直接退出。
0x03 对nginx配置文件的说明
对nginx的配置与其他配置没什么区别,我们使用如下的配置文件内容。
/etc/nginx/nginx.conf 配置文件内容:
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
| user nginx;
worker_processes 2;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
|
/etc/nginx/conf.d/default.conf 配置文件内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| server {
listen 80;
server_name localhost;
#access_log logs/host.access.log main;
#error_log logs/host.error.log notice;
location / {
root /usr/local/nginx/www;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
|
用户可以根据的需要进行调整。
0x04 对源代码包的说明
该文件是nginx的源代码包,我们可以点击该下载链接:
nginx-1.25.4.tar.gz
。
或者到官网
https://nginx.org/en/download.html
下载其他的版本:

0x05 构建镜像
将上述文件准备妥当之后,我们使用如下命令开始构建镜像:
1
| $ sudo docker build --build-arg VERSION=1.0.0 -t nginx-ubuntu:1.0.0 .
|
命令执行过程如下所示:

可见上述构建命令执行完毕之后,我们使用 sudo docker images 命令可以看到本地已经生成了我们的镜像 nginx-ubuntu。
0x06 启动容器
nginx-ubuntu:1.0.0镜像成功生成之后,我们开始测试下启动容器,看看该容器是否能够正确的完成我们预设的功能。使用如下命令启动容器:
1
| $ sudo docker run -p 80:80 -d nginx-ubuntu:1.0.0
|

通过上图可以看到,我们定制的nginx-ubuntu镜像成功启动了,并且可以在宿主机上正常访问容器中的Nginx服务。
0x07 发布镜像
至此,我们已经成功制作了我们所需的镜像,并且顺利运行起来了。下面的工作是我们将其打包发布到DockerHub网站上,供我们后续下载使用。
第一步,你需要在
https://hub.docker.com
网站注册自己的账号。如下图所示:

第二步,注册成功之后,在构建服务器上登录该账号。如下图所示:

第三步,在构建服务器上为镜像打tag。
1
2
| $ sudo docker image tag nginx-ubuntu:1.0.0 mancodenet/nginx-ubuntu:1.0.0
$ sudo docker image tag nginx-ubuntu:1.0.0 mancodenet/nginx-ubuntu:latest
|
注意:mancodenet是我在hub.docker.com网站的账号,这里需要换成你自己的账号。
执行过程如下图所示:

第四步,推送镜像到DockerHub服务器。
1
2
| $ sudo docker push mancodenet/nginx-ubuntu:1.0.0
$ sudo docker push mancodenet/nginx-ubuntu:latest
|
执行过程如下图所示:

第五步,我们看下DockerHub上我们推送的镜像。如下图所示:

我们点击进去,看下该镜像的详细情况。如下图所示:

0x08 拉取nginx-ubuntu镜像
上述所有完成之后,我们来个实战测试,就是清空当前构建服务器Docker的所有缓存数据后(或者在一个新的服务器上),从DockerHub拉取 nginx-ubuntu 镜像,然后运行。
首先,我们使用如下命令,清空本地所有容器、镜像、缓存:
1
2
3
4
5
6
7
8
9
10
11
| # 停止所有运行的容器
$ sudo docker stop $(sudo docker ps -aq)
# 删除所有的容器
$ sudo docker rm $(sudo docker ps -aq)
# 删除所有的镜像
$ sudo docker rmi -f $(sudo docker images -q)
# 清空本地的缓存
$ sudo docker system prune -a
|
执行过程如下图所示:

清理前后的数据缓存对比,下图是执行之前:

下图是执行之后:

然后,我们使用如下命令从DockerHub拉取镜像,然后运行:
1
2
3
| $ sudo docker pull mancodenet/nginx-ubuntu:1.0.0
$ sudo docker run -p 80:80 -d mancodenet/nginx-ubuntu:1.0.0
|
执行过程如下图所示:
