构建一个自己的nginx-docker
折腾党再次出发……
话说经过上次失败的面试之后,还是在师兄的帮助下拿到了offer。从此我就转行成一个程序员了。但是路是漫长的,开始是痛苦的,连续两周,我都淹没在各种新名词的汪洋大海之中不可自拔,偏偏又不想只看懂业务逻辑,想要看懂整个模块,于是一大堆东西看的头晕脑胀。
其中包括Docker。其实Docker的大名早已如雷贯耳,作为一个折腾党不知道是不可能的,但是从来没有实践过。因为在没真的用docker之前,我一直以为我偏爱直接在系统上折腾的,接触了docker之后发现我错了……系统折腾坏了那是真崩溃,但是docker折腾坏了大不了再来一份。为了加深对Docker的理解,决定自己把VPS上的那些什么nginx啊,wordpress啊之类的全都整成docker。
首先来了解一下Docker
工欲善其事、必先利其器。对于我这种看教程从来看不明白的蠢货来说,只有看那种从0开始的文档才能大概拎清楚状况。我是看这个的:
OK,关灯,咱们开始
安装docker
安全第一,不敢在VPS上直接上手,在本地虚拟机上先进行了测试。
环境是Ubuntu-server-18.04,几乎纯净。我直接用root用户操作的,所以省略了所有的sudo。乖孩子都不应该学我。
# 安装apt-get的https支持
apt-get update
apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | apt-key add -
# 添加docker源。官方不建议从未添加docker的源中直接apt-get install docker
add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"
# 安装docker
apt-get update
apt-get install docker-ce
启动docker
systemctl enable docker
systemctl start docker
把基础镜像拉下来
# 偏爱debian 8……
docker pull debian:8
开始制作
参照了浮生十六记:手动更新OPENSSL及NGINX,支持HTTP2
我先在本地pull了一个docker nginx,然后history查看了一下他的构建步骤,其中有段超长的部分,也可以做参考。
docker pull nginx
docker history nginx
这个输出放在后面再说。
先写个Dockerfile文件。
FROM debian:8
ENV NGINX_VERSION 1.15.3
RUN buildDeps="\
apt-utils gcc libc6-dev make wget \
" \
&& libs="\
perl libfindbin-libs-perl zlib1g zlib1g-dev libpcre3 libpcre3-dev \
libxml2-dev libgd-dev libgd3" \
&& rm /etc/apt/sources.list \
&& echo "deb http://mirrors.huaweicloud.com/debian/ jessie main non-free contrib" >> /etc/apt/sources.list \
&& echo "deb-src http://mirrors.huaweicloud.com/debian/ jessie main non-free contrib" >> /etc/apt/sources.list \
&& apt-get update && apt-get install -y buildDeps && apt-get install -ylibs \
&& mkdir /tmp/openssl && cd /tmp/openssl && wget https://www.openssl.org/source/openssl-1.1.1.tar.gz && tar xvf openssl-1.1.1.tar.gz && cd openssl-1.1.1 && ./config shared zlib \
&& make && make install \
&& rm -rf /tmp/openssl && ln -s /usr/local/lib/libssl.so.1.1 /usr/lib/libssl.so.1.1 && ln -s /usr/local/lib/libcrypto.so.1.1 /usr/lib/libcrypto.so.1.1 \
&& mkdir /tmp/nginx && cd /tmp/nginx && wget http://nginx.org/download/nginx-NGINX_VERSION.tar.gz && tar xvf nginx-NGINX_VERSION.tar.gz && cd nginx-NGINX_VERSION \
&& ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --with-http_image_filter_module --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 --user=www-data --group=www-data --with-compat --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro' \
&& make && make install \
&& rm -rf /tmp/nginx && mkdir -p /var/cache/nginx/client_temp \
&& apt-get purge -y --auto-removebuildDeps && rm -rf /var/lib/apt/lists/*
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
第一行要求必须是FROM xxx这样的格式,xxx是基础镜像,如果想从头建立,可以使用FROM scratch,就是完全空白镜像,什么也没有,现在就是“上帝说:要有光”的时刻了,但我肯定不敢那么干啊。
所以第一行指明了我这个nginx是基于什么构建的,可见是基于debian:8
之后就像操作linux系统一样开整,RUN后面那一大堆就是一大堆linux命令,用于在debian:8这个基础镜像上安装nginx的,可以看到我先安装了openssl,又安装了nginx,都是最新版。
还注意到我在每一步执行完毕之后都进行了清理,删除了安装包,并在最后直接apt-get remove了make相关的包,尽量减小文件的体积。
最后的CMD ["nginx", "-g", "daemon off;"]是指这个包的入口,即如果你不指明其他入口点来运行这个镜像的话,那么镜像将用nginx -g dameon off;来启动。
之后我们来build
docker build -t nginx:test .
最后的.是指明上下文环境,不能删除。在冗长的刷屏和风扇的呼啸之后,终于我们迎来了下面的提示:
Successfully built c8e4aeecc660
Successfully tagged nginx:test
赶紧运行一下试试:
docker run --rm -p 80:80 -d nginx:test
然后curl一下:
$ curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
大功告成了。
比较官方镜像
其实制作Nginx镜像一点意义都没有,因为显然官方的镜像更成熟、好用。我做这个纯粹是为了帮助自己理解Docker。做完后用以下命令比较官方镜像和自己制作的镜像。
$ docker history nginx:latest
IMAGE CREATED CREATED BY SIZE
06144b287844 12 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 12 days ago /bin/sh -c #(nop) STOPSIGNAL [SIGTERM] 0B
<missing> 12 days ago /bin/sh -c #(nop) EXPOSE 80/tcp 0B
<missing> 12 days ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
<missing> 12 days ago /bin/sh -c set -x && apt-get update && apt… 53.8MB
<missing> 12 days ago /bin/sh -c #(nop) ENV NJS_VERSION=1.15.3.0.… 0B
<missing> 12 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.3-… 0B
<missing> 12 days ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 12 days ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 12 days ago /bin/sh -c #(nop) ADD file:e6ca98733431f75e9… 55.3MB
而我的输出呢
# docker history nginx:test
IMAGE CREATED CREATED BY SIZE
c8e4aeecc660 14 minutes ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
6ab3e3561d53 14 minutes ago /bin/sh -c #(nop) EXPOSE 443 80 0B
cb7f2d35f387 14 minutes ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx… 22B
c4419d06d164 14 minutes ago /bin/sh -c buildDeps=" apt-utils gcc … 86.3MB
a7b37ba65e63 43 minutes ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.15.3 0B
7f228954ce78 12 days ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 12 days ago /bin/sh -c #(nop) ADD file:8d73a09e59fe50289… 127MB
可以看到两处明显的不同,第一是基础层大小完全不同,这是为什么呢?
因为我使用的基础镜像是debian:8,这个镜像是比较大的。但官方nginx使用的是什么呢?
nginx:alpine
This image is based on the popular Alpine Linux project, available in the alpine official image. Alpine Linux is much smaller than most distribution base images (~5MB), and thus leads to much slimmer images in general.This variant is highly recommended when final image size being as small as possible is desired. The main caveat to note is that it does use musl libc instead of glibc and friends, so certain software might run into issues depending on the depth of their libc requirements. However, most software doesn’t have an issue with this, so this variant is usually a very safe choice. See this Hacker News comment thread for more discussion of the issues that might arise and some pro/con comparisons of using Alpine-based images.
To minimize image size, it’s uncommon for additional related tools (such as git or bash) to be included in Alpine-based images. Using this image as a base, add the things you need in your own Dockerfile (see the alpine image description for examples of how to install packages if you are unfamiliar).
以上资料来自Docker-hub:nginx项目
用了一个更加精简的包,而这个包与debian:8的体积差别就有70M。可见基础镜像的选择对于镜像大小影响极大。网上有那种用busybox的极限轻量包,整个文件系统都是复制进去的,这就得自己很清醒到底在做什么才可以,我这样对linux半吊子理解的,肯定玩不了这个。
那为什么我的正经镜像层还是大了那么多呢?其实主要是大在编译nginx时--with-http_image_filter_module这个参数上了。这会要求你下载libgd-dev libgd3,这两个包就差不多20M,官方并没有包含这个包,但这个包在我的VPS上的网盘filerun中要用,所以我编译进去了。减去这个20M的话……好吧还是大一些,但是只有10M也可以接受了,毕竟我搞不清楚哪些可以删哪些不可以删,在编译过程中我发现有不少/usr/local/doc这样的文件,或者/usr/local/man这样的东西,可见都是文档或者给man用的,应该也一样可以删除,或许删除后能进一步精简镜像体积,暂时就没空测试啦。
下一个坑
折腾党总是要给自己挖好下一个坑,才方便往里跳。下一个坑是nginx配置文件以及容器间互联,以及docker-compose的使用。敬请期待吧呦……
0 条评论