alinode 官方镜像分析并提取 Dockerfile

上篇介绍了 alinode 自定义封装,但毕竟不是官网原配置,群里也有人吐槽过官网镜像太大。
所以这次分析官网镜像,看看到底为什么这么多大,顺便提取官网 Dockerfile。

官网镜像介绍

目前有 33-alpine 两种版本。
3 镜像 732MB,为什么这么大?
3-alpine 我提 issue 后正常了,仅仅 71.5MB。

其实无关大小,大家用镜像,无非图个省事,但没有 Dockerfile 用的人也很慌。
上一篇也提到了,官网有个一年多没更新过的 Dockerfile,其实也能用。

我们还是来着重分析下 3 版本,看看为什么这么大。

docker image 分析

逆向分析镜像有两种方法。
一种是 docker history 可以看到每一层的配置,但包括了从底层镜像开始的所有配置,所以会很杂乱。
另一种是 docker save 导出 tar 包,解压后,不仅可以得到每一层的配置,还能详细的看到每一层的文件增删情况。

这里我们讨论 docker history 方法,因为够用了。

docker history

1
$ docker history --no-trunc registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3 > history.md

这里加了 --no-trunc 参数,不截断数据,并且导出到 history.md 文件中。

ps: 由于 --no-trunc 的结果太长,不合适博客展示,所以这里贴了下截断后的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
e649e72af9a2 2 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["/start-agent… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) COPY file:cdecc22ff2ae3835… 178B
<missing> 2 weeks ago /bin/sh -c #(nop) COPY file:2446f9972d7e6dfa… 885B
<missing> 2 weeks ago /bin/sh -c ENABLE_NODE_LOG=NO npm install -g… 8.18MB
<missing> 2 weeks ago /bin/sh -c curl -SLO "http://alinode.aliyun.… 54.2MB
<missing> 2 weeks ago /bin/sh -c #(nop) ENV HOME=/root 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV NODE_LOG_DIR=/tmp 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV ENABLE_NODE_LOG=YES 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV ALINODE_VERSION=3.12.0 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 3 weeks ago /bin/sh -c set -ex && for key in 6A010… 4.5MB
<missing> 3 weeks ago /bin/sh -c #(nop) ENV YARN_VERSION=1.9.4 0B
<missing> 3 weeks ago /bin/sh -c ARCH= && dpkgArch="$(dpkg --print… 53.8MB
<missing> 3 weeks ago /bin/sh -c #(nop) ENV NODE_VERSION=8.12.0 0B
<missing> 4 weeks ago /bin/sh -c set -ex && for key in 94AE3… 137kB
<missing> 4 weeks ago /bin/sh -c groupadd --gid 1000 node && use… 335kB
<missing> 4 weeks ago /bin/sh -c set -ex; apt-get update; apt-ge… 320MB
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install… 123MB
<missing> 4 weeks ago /bin/sh -c set -ex; if ! command -v gpg > /… 0B
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install… 41.1MB
<missing> 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:8d73a09e59fe50289… 127MB

IMAGE 这列,全部丢失,只有最后一层有个 id。
CREATED BY 是我们关注的主体,其他列都可以忽略。
当然你也可以看看 SIZE 太大的层可以去优化下命令。

CREATED BY 列中,全部是 /bin/sh -c 开头,但有的有 #(nop) 有的没有,这是为什么?
我也不知道,但仔细观察,其实可以发现没 #(nop)RUN 指令的配置。

那么简单了,所有 /bin/sh -c #(nop) 删除,剩下的所有 /bin/sh -c 改成 RUN 就是我们要的 dockerfile 配置了。
再观察下发现好像最下面的是底层镜像配置,所以应该将结果倒序下才是我们要的 dockerfile。

这里写了个 bash 来辅助我们输出结果

1
2
3
4
5
6
7
8
docker history \
--no-trunc \
--format "{{.CreatedBy}}" \ # 只输出 CREATED BY 字段
registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3 \
| perl -e 'print reverse <>' \ # 倒序
| sed 's/\/bin\/sh -c #(nop) //' # 删除 #(nop)
| sed 's/\/bin\/sh -c /RUN /' \ # 替换 RUN 指令
> dockerfile

保存为 history.sh 执行 sh history.sh 得到 dockerfile 文件,内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ADD file:8d73a09e59fe50289a6d0c019302aefe2e00ac6411e82404389c0c83f50cf08a in / 
CMD ["bash"]
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl netbase wget && rm -rf /var/lib/apt/lists/*
RUN set -ex; if ! command -v gpg > /dev/null; then apt-get update; apt-get install -y --no-install-recommends gnupg dirmngr ; rm -rf /var/lib/apt/lists/*; fi
RUN apt-get update && apt-get install -y --no-install-recommends bzr git mercurial openssh-client subversion procps && rm -rf /var/lib/apt/lists/*
RUN set -ex; apt-get update; apt-get install -y --no-install-recommends autoconf automake bzip2 dpkg-dev file g++ gcc imagemagick libbz2-dev libc6-dev libcurl4-openssl-dev libdb-dev libevent-dev libffi-dev libgdbm-dev libgeoip-dev libglib2.0-dev libjpeg-dev libkrb5-dev liblzma-dev libmagickcore-dev libmagickwand-dev libncurses5-dev libncursesw5-dev libpng-dev libpq-dev libreadline-dev libsqlite3-dev libssl-dev libtool libwebp-dev libxml2-dev libxslt-dev libyaml-dev make patch xz-utils zlib1g-dev $( if apt-cache show 'default-libmysqlclient-dev' 2>/dev/null | grep -q '^Version:'; then echo 'default-libmysqlclient-dev'; else echo 'libmysqlclient-dev'; fi ) ; rm -rf /var/lib/apt/lists/*
RUN groupadd --gid 1000 node && useradd --uid 1000 --gid node --shell /bin/bash --create-home node
RUN set -ex && for key in 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 FD3A5288F042B6850C66B31F09FE44734EB7990E 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 DD8F2338BAE7501E3DD5AC78C273792F7D83545D C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 B9AE9905FFD7803F25714661B63B535A4C206CA9 56730D5401028683275BD23C23EFEFE93C4CFFFE 77984A986EBC2AA786BC0F66B01FBB92821C587A 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 ; do gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; done
ENV NODE_VERSION=8.12.0

RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" && case "${dpkgArch##*-}" in amd64) ARCH='x64';; ppc64el) ARCH='ppc64le';; s390x) ARCH='s390x';; arm64) ARCH='arm64';; armhf) ARCH='armv7l';; i386) ARCH='x86';; *) echo "unsupported architecture"; exit 1 ;; esac && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc && grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - && tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner && rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt && ln -s /usr/local/bin/node /usr/local/bin/nodejs
ENV YARN_VERSION=1.9.4
RUN set -ex && for key in 6A010C5166006599AA17F08146C2130DFD2497F5 ; do gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; done && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz && mkdir -p /opt && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz
CMD ["node"]
ENV ALINODE_VERSION=3.12.0

ENV ENABLE_NODE_LOG=YES
ENV NODE_LOG_DIR=/tmp
ENV HOME=/root
RUN curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/alinode-v$ALINODE_VERSION-linux-x64.tar.gz" && curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/SHASUMS256.txt" && grep " alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt | sha256sum -c - && tar -zxvf "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 --no-same-owner && rm "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt
RUN ENABLE_NODE_LOG=NO npm install -g @alicloud/agenthub --registry=https://registry.npm.taobao.org
COPY file:2446f9972d7e6dfaebacf7c2defe4a0425a23e4cf98ca598f61840e9f4fe1d67 in /root
COPY file:cdecc22ff2ae3835fb36e08a92aa71e8857bc4048dccdae1b6bad0061de3b32f in /
ENTRYPOINT ["/start-agenthub.sh"]

虽然还是有点乱,但至少得到了所有配置,接下来我们分析这些配置。

分析 history 提取最终 Dockerfile

这里先使用下我写的一个工具,重新得到格式化后的 dockerfile,方便我们分析,这个工具下一篇文章详细介绍。

1
$ npx dockerfile-from-image registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3 > dockerfile

PS: 不知道 npx 是什么或者 npx 命令无效的同学,请自行百度,这是神器,必须掌握。

得到如下 dockerfile 配置。

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
FROM registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3
ADD file:8d73a09e59fe50289a6d0c019302aefe2e00ac6411e82404389c0c83f50cf08a in /
CMD ["bash"]
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
netbase \
wget \
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \
if ! command -v gpg > /dev/null; then \
apt-get update; \
apt-get install -y --no-install-recommends \
gnupg \
dirmngr \
; \
rm -rf /var/lib/apt/lists/*; \
fi
RUN apt-get update && apt-get install -y --no-install-recommends \
bzr \
git \
mercurial \
openssh-client \
subversion \
procps \
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends \
autoconf \
automake \
bzip2 \
dpkg-dev \
file \
g++ \
gcc \
imagemagick \
libbz2-dev \
libc6-dev \
libcurl4-openssl-dev \
libdb-dev \
libevent-dev \
libffi-dev \
libgdbm-dev \
libgeoip-dev \
libglib2.0-dev \
libjpeg-dev \
libkrb5-dev \
liblzma-dev \
libmagickcore-dev \
libmagickwand-dev \
libncurses5-dev \
libncursesw5-dev \
libpng-dev \
libpq-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
libtool \
libwebp-dev \
libxml2-dev \
libxslt-dev \
libyaml-dev \
make \
patch \
xz-utils \
zlib1g-dev \
$( \
if apt-cache show 'default-libmysqlclient-dev' 2>/dev/null | grep -q '^Version:'; then \
echo 'default-libmysqlclient-dev'; \
else \
echo 'libmysqlclient-dev'; \
fi \
) \
; \
rm -rf /var/lib/apt/lists/*
RUN groupadd --gid 1000 node \
&& useradd --uid 1000 --gid node --shell /bin/bash --create-home node
RUN set -ex \
&& for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
56730D5401028683275BD23C23EFEFE93C4CFFFE \
77984A986EBC2AA786BC0F66B01FBB92821C587A \
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
; do \
gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done
ENV NODE_VERSION=8.12.0

RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
&& case "${dpkgArch##*-}" in \
amd64) ARCH='x64';; \
ppc64el) ARCH='ppc64le';; \
s390x) ARCH='s390x';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armv7l';; \
i386) ARCH='x86';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
ENV YARN_VERSION=1.9.4
RUN set -ex \
&& for key in \
6A010C5166006599AA17F08146C2130DFD2497F5 \
; do \
gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz
CMD ["node"]
ENV ALINODE_VERSION=3.12.0

ENV ENABLE_NODE_LOG=YES
ENV NODE_LOG_DIR=/tmp
ENV HOME=/root
RUN curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/alinode-v$ALINODE_VERSION-linux-x64.tar.gz" \
&& curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/SHASUMS256.txt" \
&& grep " alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt | sha256sum -c - \
&& tar -zxvf "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt
RUN ENABLE_NODE_LOG=NO npm install -g @alicloud/agenthub --registry=https://registry.npm.taobao.org
COPY file:2446f9972d7e6dfaebacf7c2defe4a0425a23e4cf98ca598f61840e9f4fe1d67 in /root
COPY file:cdecc22ff2ae3835fb36e08a92aa71e8857bc4048dccdae1b6bad0061de3b32f in /
ENTRYPOINT ["/start-agenthub.sh"]

这样看就非常清晰了。

开头的 ADD file:xxx in /CMD ["bash"] 明显就是基础镜像,接着往下看。
接下来各种 RUN 安装一大堆开发工具。。
直到 RUN groupadd --gid 1000 node \ 才是我们熟悉的 node 环境相关的配置。
接着往下看,,一脸懵逼,怎么在安装官网 node ???不是说好的 alinode 么?
我们继续往下看,直到 ENV ALINODE_VERSION=3.12.0 才是我们 alinode 的配置。
下面不到10个指令,命令简洁明了,设置相关环境变量,然后从阿里云下载 alinode,解压到 /usr/local 目录。
然后是安装 agenthub 接着添加两个文件到 root目录 和 根目录。

其实是 default.config.js 复制到 /root
然后是 start-agenthub.sh 复制到 / 并作为 ENTRYPOINT 入口。

怎么提取这两个文件,下面详细说明,我们先整理 dockerfile。

从这里看,其实就是最后几条质量有用没其他都是些啥?
如果你对 node 镜像熟悉的话,其实不难发现,他是 node:8 的镜像。

1
$ npx dockerfile-from-image node:8 > dockerfile

得到

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
FROM node:8
ADD file:8d73a09e59fe50289a6d0c019302aefe2e00ac6411e82404389c0c83f50cf08a in /
CMD ["bash"]
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
netbase \
wget \
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \
if ! command -v gpg > /dev/null; then \
apt-get update; \
apt-get install -y --no-install-recommends \
gnupg \
dirmngr \
; \
rm -rf /var/lib/apt/lists/*; \
fi
RUN apt-get update && apt-get install -y --no-install-recommends \
bzr \
git \
mercurial \
openssh-client \
subversion \
procps \
&& rm -rf /var/lib/apt/lists/*
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends \
autoconf \
automake \
bzip2 \
dpkg-dev \
file \
g++ \
gcc \
imagemagick \
libbz2-dev \
libc6-dev \
libcurl4-openssl-dev \
libdb-dev \
libevent-dev \
libffi-dev \
libgdbm-dev \
libgeoip-dev \
libglib2.0-dev \
libjpeg-dev \
libkrb5-dev \
liblzma-dev \
libmagickcore-dev \
libmagickwand-dev \
libncurses5-dev \
libncursesw5-dev \
libpng-dev \
libpq-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
libtool \
libwebp-dev \
libxml2-dev \
libxslt-dev \
libyaml-dev \
make \
patch \
xz-utils \
zlib1g-dev \
$( \
if apt-cache show 'default-libmysqlclient-dev' 2>/dev/null | grep -q '^Version:'; then \
echo 'default-libmysqlclient-dev'; \
else \
echo 'libmysqlclient-dev'; \
fi \
) \
; \
rm -rf /var/lib/apt/lists/*
RUN groupadd --gid 1000 node \
&& useradd --uid 1000 --gid node --shell /bin/bash --create-home node
RUN set -ex \
&& for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
56730D5401028683275BD23C23EFEFE93C4CFFFE \
77984A986EBC2AA786BC0F66B01FBB92821C587A \
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
; do \
gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done
ENV NODE_VERSION=8.12.0

RUN ARCH= && dpkgArch="$(dpkg --print-architecture)" \
&& case "${dpkgArch##*-}" in \
amd64) ARCH='x64';; \
ppc64el) ARCH='ppc64le';; \
s390x) ARCH='s390x';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armv7l';; \
i386) ARCH='x86';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
ENV YARN_VERSION=1.9.4
RUN set -ex \
&& for key in \
6A010C5166006599AA17F08146C2130DFD2497F5 \
; do \
gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz
CMD ["node"]

是不是一毛一样?

所以最终的 Dockerfile 是这样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM node:8

ENV ALINODE_VERSION=3.12.0
ENV ENABLE_NODE_LOG=YES
ENV NODE_LOG_DIR=/tmp
ENV HOME=/root

RUN curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/alinode-v$ALINODE_VERSION-linux-x64.tar.gz" \
&& curl -SLO "http://alinode.aliyun.com/dist/new-alinode/v$ALINODE_VERSION/SHASUMS256.txt" \
&& grep " alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt | sha256sum -c - \
&& tar -zxvf "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "alinode-v$ALINODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt

RUN ENABLE_NODE_LOG=NO npm install -g @alicloud/agenthub --registry=https://registry.npm.taobao.org

COPY default.config.js /root
COPY start-agenthub.sh /

ENTRYPOINT ["/start-agenthub.sh"]

瞬间明朗了,也知道为什么镜像这么大了。
node:8 Dockerfile 镜像依赖 buildpack-deps:jessie

从刚才的配置也看到了,几乎包含了所有开发编译时所需的各种工具。

那么还有个问题,default.config.js, start-agenthub.sh 怎么提取?

1
2
$ docker run --rm -it registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3 cat /start-agenthub.sh > start-agenthub.sh
$ docker run --rm -it registry.cn-hangzhou.aliyuncs.com/aliyun-node/alinode:3 cat /root/default.config.js > default.config.js

好了 Dockerfile, default.config.js, start-agenthub.sh 都得到了。
接着就可以 docker build -t alinode . 编译镜像了。

当然,你也可以为所欲为,各种魔改。

小结

我是一个喜欢刨根究底的人,这个事情其实上个月该做的,但各种琐事以及懒惰,拖到这个月才处理。
但结果是好的,把事情搞清楚了,以后遇到没有 Dockerfile 的镜像也可以分析出个大概。