0%
Docker#003#基于Docker+Ubuntu制作镜像nginx-ubuntu

前文我们使用官方提供的hello world镜像作为验证例子,本文我们将基于Nginx+Ubuntu,根据我们的需求定制Docker镜像,并将其上传到DockerHub上,供以后多次使用。

准备文件

在开始构建镜像之前,我们首先看下构建一个基于Nginx+Ubuntu的Docker镜像,所需要的基本文件。文件目录结构,是按我的习惯布置的,读者可自行修改。如下文档可以访问Github仓库 [ mancodenet/images/docker-nginx-ubuntu ] 下载。

对文件 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的进程挂掉了,该容器便会自动直接退出。

对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;
}
}

用户可以根据的需要进行调整。

对文件 nginx-1.25.4.tar.gz 的说明

该文件是nginx的源代码包,我们可以点击该下载链接:nginx-1.25.4.tar.gz

或者到官网 https://nginx.org/en/download.html 下载其他的版本:

构建镜像

将上述文件准备妥当之后,我们使用如下命令开始构建镜像:

1
$ sudo docker build --build-arg VERSION=1.0.0 -t nginx-ubuntu:1.0.0 .

命令执行过程如下所示:

可见上述构建命令执行完毕之后,我们使用 sudo docker images 命令可以看到本地已经生成了我们的镜像 nginx-ubuntu。

启动容器

nginx-ubuntu:1.0.0镜像成功生成之后,我们开始测试下启动容器,看看该容器是否能够正确的完成我们预设的功能。使用如下命令启动容器:

1
$ sudo docker run -p 80:80 -d nginx-ubuntu:1.0.0

通过上图可以看到,我们定制的nginx-ubuntu镜像成功启动了,并且可以在宿主机上正常访问容器中的Nginx服务。

发布镜像

至此,我们已经成功制作了我们所需的镜像,并且顺利运行起来了。下面的工作是我们将其打包发布到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上我们推送的镜像。如下图所示:

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

清空本地所有容器、镜像、缓存,然后测试从DockerHub拉取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

执行过程如下图所示: