04/23/2017

Docker 学习笔记(二) - 构建 nyancat-server 镜像

用了 Docker 快一个月了,不过都是用别人的镜像。正好看到 github 上有趣的 nyancat 项目便构建一个镜像玩玩。

这个就是我要做的东西:「Nyan Cat Telnet Server」。

目前 DockerHub 上有一些 nyancat 的镜像。不过支持 telnet 的很多都是 node 版本的而且镜像体积都得几十兆,运行时一直 100% 内存 :(

我就想用 alpine:3.5 [3.99MB] 镜像做个特别轻、特别干净的镜像。

0x00 - 准备工作

Docker 环境都在 「Docker 学习笔记(一) - 搭建 Firekylin 博客」时设置好了。

0x01 - 编写镜像的 Dockerfile

读了很多文章后总结出来的结论就是一定要用 Dockerfile 写镜像而不是用 docker commit 功能。主要优势就是易维护,易分享,易集成。

试了半天写出了下面这坨:

Dockerfile

FROM alpine:3.5
LABEL maintainer="Wei He <[email protected]>"

RUN \
    apk upgrade --update && \
    apk add g++ make git autoconf automake

RUN \
    cd /tmp && git clone https://github.com/klange/nyancat.git && \
    cd /tmp/nyancat && make && \
    cp ./src/nyancat /usr/local/bin/ && \
    cd / && rm -rf /tmp/nyancat

RUN \
    cd /tmp && git clone https://github.com/ddhhz/onenetd.git && \
    cd /tmp/onenetd && autoreconf -vfi && ./configure && make && \
    cp ./onenetd /usr/local/bin && \
    cd / && rm -rf /tmp/onenetd

RUN \
    apk del --purge g++ make git autoconf automake

EXPOSE 23

ENTRYPOINT ["onenetd", "-v1", "0", "23", "nyancat", "--telnet"]

我把 RUN 部分分为了 4 个步骤,安装 dependencies、安装 nyancat、安装 onenetd、清理 dependencies,应该是比较清晰明了的。

0x02 - 构建镜像

这一步我写 Dockerfile 测试时重复了好多遍。

$ docker build -f Dockerfile . -t ddhhz/nyancat-server

Output 长这样:

Sending build context to Docker daemon 4.099 MB
Step 1/8 : FROM alpine:3.5
3.5: Pulling from library/alpine
Digest: sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4
Status: Downloaded newer image for alpine:3.5
 ---> 4a415e366388
Step 2/8 : LABEL maintainer "Wei He "
 ---> Running in 6dcfd2925e26
 ---> d5045af5f75e
Removing intermediate container 6dcfd2925e26
Step 3/8 : RUN apk upgrade --update &&     apk add g++ make git autoconf automake
 ---> Running in 31c4a3cc086b
...
 ---> f2a2dd1731d8
Removing intermediate container 31c4a3cc086b
Step 4/8 : RUN cd /tmp && git clone https://github.com/klange/nyancat.git &&     cd /tmp/nyancat && make &&     cp ./src/nyancat /usr/local/bin/ &&     cd / && rm -rf /tmp/nyancat
 ---> Running in e4446629a4fd
...
 ---> c349461e3fc7
Removing intermediate container e4446629a4fd
Step 5/8 : RUN cd /tmp && git clone https://github.com/ddhhz/onenetd.git &&     cd /tmp/onenetd && autoreconf -vfi && ./configure && make &&     cp ./onenetd /usr/local/bin &&     cd / && rm -rf /tmp/onenetd
 ---> Running in 5c8198ecc381
...
 ---> e2a1d37466f6
Removing intermediate container 5c8198ecc381
Step 6/8 : RUN apk del --purge g++ make git autoconf automake
 ---> Running in f8b3c1a8c33c
...
 ---> 794d44a3ae67
Removing intermediate container f8b3c1a8c33c
Step 7/8 : EXPOSE 23
 ---> Running in 9264e44de3be
 ---> 09a57d263cc7
Removing intermediate container 9264e44de3be
Step 8/8 : ENTRYPOINT onenetd -v1 0 23 nyancat --telnet
 ---> Running in fb9d7ccc00a5
 ---> 0e0b79a8b21e
Removing intermediate container fb9d7ccc00a5
Successfully built 0e0b79a8b21e

看起来总共有 8 层。多层的优势就是更改了一层的代码不需要重构所有的层,比如:更改了 nyancat 构建代码重新 build 就不需要重新运行 apk add 安装命令了。

0x03 - 运行容器

运行

$ docker run -d --name nyancat-server --restart=always -p 23:23 ddhhz/nyancat-server

然后

$ telnet localhost

就可以看到美丽的 nyancat 了!

0x04 - 镜像瘦身法

惊吓!容器太大了!

突然发现镜像大小。。。有。。。221 MB。。

REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
ddhhz/nyancat-server   latest              0e0b79a8b21e        13 minutes ago      221 MB
alpine                 3.5                 4a415e366388        7 weeks ago         3.99 MB
joshgordon/nyancat-telnet                latest              ea00a2adcc4b        11 months ago       42 MB

我是怎么做到的!!!给 alpine 美女喂了点东西就从 3.99 MB 涨到了 221 MB ?!

优化方法

其实就是刚才的层的问题。Docker 会保存下来每一层。安装了一堆包后保存了一下,删除包后也有保存,但是,并不会删除之前保存的层。

多层在开发过程中是很有优势的,但是在发布时候应该尽可能用最少的层。

于是新的 Dockerfile 诞生了:

FROM alpine:3.5
LABEL \
    maintainer="Wei He <[email protected]>" \
    verion="1.0" \
    description="Nyancat Telnet Server"

RUN \
    apk upgrade --update && \
    apk add g++ make git autoconf automake && \

    cd /tmp && git clone https://github.com/klange/nyancat.git && \
    cd /tmp/nyancat && make && \
    cp ./src/nyancat /usr/local/bin/ && \
    cd / && rm -rf /tmp/nyancat && \

    cd /tmp && git clone https://github.com/ddhhz/onenetd.git && \
    cd /tmp/onenetd && autoreconf -vfi && ./configure && make && \
    cp ./onenetd /usr/local/bin && \
    cd / && rm -rf /tmp/onenetd && \

    apk del --purge g++ make git autoconf automake && \

    :

EXPOSE 23

ENTRYPOINT ["onenetd", "-v1", "0", "23", "nyancat", "--telnet"]

重新 docker build

$ docker build -f Dockerfile . -t ddhhz/nyancat-server
Sending build context to Docker daemon 65.54 kB
Step 1/5 : FROM alpine:3.5
 ---> 4a415e366388
Step 2/5 : LABEL maintainer "Wei He " verion "1.0" description "Nyancat Telnet Server"
 ---> Running in cec170bdbdab
 ---> b903ab18f6ab
Removing intermediate container cec170bdbdab
Step 3/5 : RUN apk upgrade --update &&     apk add g++ make git autoconf automake &&     cd /tmp && git clone https://github.com/klange/nyancat.git &&     cd /tmp/nyancat && make &&     cp ./src/nyancat /usr/local/bin/ &&     cd / && rm -rf /tmp/nyancat &&     cd /tmp && git clone https://github.com/ddhhz/onenetd.git &&     cd /tmp/onenetd && autoreconf -vfi && ./configure && make &&     cp ./onenetd /usr/local/bin &&     cd / && rm -rf /tmp/onenetd &&     apk del --purge g++ make git autoconf automake &&     :
 ---> Running in 05acf0bbca6a
...
 ---> a47c97ca49c9
Removing intermediate container 05acf0bbca6a
Step 4/5 : EXPOSE 23
 ---> Running in a7e6e77354c9
 ---> 1b1c44e12b84
Removing intermediate container a7e6e77354c9
Step 5/5 : ENTRYPOINT onenetd -v1 0 23 nyancat --telnet
 ---> Running in cf5a7f3f1a6a
 ---> 5ffd3f6b5393
Removing intermediate container cf5a7f3f1a6a
Successfully built 5ffd3f6b5393

已经从刚才的 8 层减少到了 5 层。Docker 保存 RUN 这层的时候我已经把多余的包都删掉了。

看看效果:

REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
ddhhz/nyancat-server   latest              5ffd3f6b5393        3 minutes ago       5.15 MB
<none>                 <none>              0e0b79a8b21e        24 minutes ago      221 MB
alpine                 3.5                 4a415e366388        7 weeks ago         3.99 MB
joshgordon/nyancat-telnet                latest              ea00a2adcc4b        11 months ago       42 MB

简直了 从刚才的 221 MB 减肥到了 5.15 MB。

Source:

0x05 - 发布到 DockerHub

流程简单列一下:

  1. 建立 Github repo 并把 Dockerfile 放进去。
  2. 登陆 https://hub.docker.com
  3. 链接 Github 账户
  4. Create Automated Build
  5. 手动 POST 或 Github push 触发 build

查看 build 记录

查看成功发布的镜像Dockerfile

Docker Stars >< Docker Pulls >< Docker Build >< Docker Image Size and Layers ><

0x06 - 服务器 nyancat telnet 服务上线

服务器防火墙打开 23 端口,运行:

$ docker run -d --name nyancat-server --restart=always -p 23:23 ddhhz/nyancat-server

Unable to find image 'ddhhz/nyancat-server:latest' locally
latest: Pulling from ddhhz/nyancat-server
627beaf3eaaf: Already exists 
cf86dd0cc659: Pull complete 
Digest: sha256:cd147440427e8fa15aaf10d0832d0491ad70eb416eaa2a9854d349533c8d32fc
Status: Downloaded newer image for ddhhz/nyancat-server:latest
3b13880ed9b1272427eca4fcab8cb206c2060d956a206d0e6fbab18693012632

成功!Demo:把 terminal 拉大一些然后 telnet nyancat.whe.me 一分钟 3 兆流量,我看看就好。已经 CNAME 到原作者的:telnet nyancat.dakko.us;或者本地测试吧。

乞丐版谷歌云从 Node 版 joshgordon/nyancat-telnet:latest 切换到 ddhhz/nyancat-server:latest 系统资源占用对比:

系统资源对比

本文链接:https://blog.whe.me/post/docker-series-2-build-image.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。