在树莓派上搭建一个docker文档的镜像站

简介

众所周知,docker文档的网站访问时很慢的,如果你没有什么特殊的方法那么你的体验会很不好,而kubernetes文档的访问那就是不能访问,所以在自己本地搭建一个文档的镜像就显得很重要了,我树莓派上使用的是swarm集群,因为是树莓派,官方并没有提供arm的镜像,所以要自己编译,如果你本地和我一样只有一个树莓派或者8个树莓派组成的swarm集群,你可以看看我的这个文章

操作

首先说下我的操作,我是使用drone做的cicd去编译的镜像,这过程很曲折,但是好在最后我还是编译出来了,因为大部分镜像是没有arm版本的,所以我有一个想法,就是想创建一个arm的镜像仓库,然后方便大家去使用,废话不多说,直接操作

首先看下docker文档的镜像仓库

https://github.com/docker/docker.github.io

里面有一个dockerfile,我们所要做的就是把这个dockerfile编译成镜像,在此之前我们先看看他的基础镜像

FROM starefossen/github-pages:198 AS builderbase
FROM scratch AS archives-false
FROM scratch AS archives-true
FROM archives-${ENABLE_ARCHIVES} AS archives
FROM alpine AS upstream-resources
FROM builderbase AS current
FROM archives AS deploy-source
FROM nginx:alpine AS deploy

里面除了starefossen/github-pages:198其实都是有arm镜像的,所以我们要编译starefossen/github-pages:198这个镜像为arm版本,所以我们要看这个镜像的repo

https://github.com/Starefossen/docker-github-pages

里面有个dockerfile,里面的基础镜像是

starefossen/ruby-node:2-6-alpine

所以在编译starefossen/github-pages:198之前我们要编译starefossen/ruby-node:2-6-alpine,所以我们再看starefossen/ruby-node:2-6-alpine的repo

https://github.com/Starefossen/docker-ruby-node

这个基础镜像的dockerfile在

https://github.com/Starefossen/docker-ruby-node/blob/master/2-6/alpine/Dockerfile

看下这个镜像的基础镜像是

FROM ruby:2-alpine

这个镜像是有arm版本的,所以我们先编译

starefossen/ruby-node:2-6-alpine

编译starefossen/ruby-node:2-6-alpine

首先他的dockerfile中有一些gpg验证是可以不用做的,如果加上会编译不成功,最终的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
FROM ruby:2-alpine


ENV NODE_MAJOR 6

RUN addgroup -g 1000 node \
&& adduser -u 1000 -G node -s /bin/sh -D node \
&& apk add --no-cache \
libstdc++ \
&& apk add --no-cache --virtual .build-deps \
binutils-gold \
curl \
g++ \
gcc \
gnupg \
libgcc \
linux-headers \
make \
python \
&& NODE_VERSION=$(curl -SL "https://nodejs.org/dist/index.tab" \
| grep "^v$NODE_MAJOR" \
| head -n 1 | awk '{ print substr($1,2) }') \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \
&& tar -xf "node-v$NODE_VERSION.tar.xz" \
&& cd "node-v$NODE_VERSION" \
&& ./configure \
&& make -j$(getconf _NPROCESSORS_ONLN) \
&& make install \
&& apk del .build-deps \
&& cd .. \
&& rm -Rf "node-v$NODE_VERSION" \
&& rm "node-v$NODE_VERSION.tar.xz"

RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
&& YARN_VERSION=$(curl -sSL --compressed https://yarnpkg.com/latest-version) \
&& curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& mkdir -p /opt/yarn \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/yarn --strip-components=1 \
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz \
&& apk del .build-deps-yarn

具体的东西你可以和他的对比下就是少了文件下载验证的过程,之后编写.drone.yml,我的如下,其实就是一个使用docker插件的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
---
kind: pipeline
type: docker
name: ruby-node

workspace:
path: /build/ruby-node

platform:
os: linux
arch: arm


steps:
- name: docker
image: plugins/docker
settings:
repo: 10.10.100.12:5000/ruby-node
tags: 2-6-alpine
insecure: true
registry: 10.10.100.12:5000
custom_dns: 114.114.114.114
...

这里我就直接推送到我的本地仓库了,编译的时候因为树莓派性能的局限性可能会很慢,之间又碰到了几次坑,所以必须要有耐心

这样子编译完成之后我们编译

starefossen/github-pages:198

编译starefossen/github-pages:198

因为我们已经把上个镜像推送到仓库了,所以我们要修改dockerfile为下面这个样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM 10.10.100.12:5000/ruby-node:2-6-alpine

ENV GITHUB_GEM_VERSION 202
ENV JSON_GEM_VERSION 1.8.6

RUN apk --update add --virtual build_deps \
build-base ruby-dev libc-dev linux-headers \
&& gem install --verbose --no-document \
json:${JSON_GEM_VERSION} \
github-pages:${GITHUB_GEM_VERSION} \
jekyll-github-metadata \
minitest \
&& apk del build_deps \
&& apk add git \
&& mkdir -p /usr/src/app \
&& rm -rf /usr/lib/ruby/gems/*/cache/*.gem

WORKDIR /usr/src/app

EXPOSE 4000 80
CMD jekyll serve -d /_site --watch --force_polling -H 0.0.0.0 -P 4000

就是修改了from字段

我的.drone.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
kind: pipeline
type: docker
name: github-pages

platform:
os: linux
arch: arm


steps:
- name: docker
image: plugins/docker
settings:
repo: 10.10.100.12:5000/github-pages
tags: 198
insecure: true
registry: 10.10.100.12:5000
custom_dns: 114.114.114.114
...

这步一般会直接编译成功,注意,路由器最好直接fq,不然alpine apk update的时候可能会很慢

最后就是大头了,编译docker.github.io镜像

编译docker.github.io镜像

这里我们也是只要修改from字段就可以了,因为整个仓库是很大的,所以使用drone编译的时候clone就会很慢,我的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
# This Dockerfile builds the docs for https://docs.docker.com/
# from the master branch of https://github.com/docker/docker.github.io
#
# Here is the sequence:
# 1. Set up base stages for building and deploying
# 2. Collect and build the archived documentation
# 3. Collect and build the reference documentation (from upstream resources)
# 4. Build static HTML from the current branch
# 5. Build the final image, combining the archives, reference docs, and
# current version of the documentation
#
# When the image is run, it starts Nginx and serves the docs at port 4000


# Engine
ARG ENGINE_BRANCH="19.03"

# Distribution
ARG DISTRIBUTION_BRANCH="release/2.7"

# Set to "false" to build the documentation without archives
ARG ENABLE_ARCHIVES=true

###
# Set up base stages for building and deploying
###
FROM 10.10.100.12:5000/github-pages:198 AS builderbase
ENV TARGET=/usr/share/nginx/html
WORKDIR /usr/src/app/md_source/

# Set vars used by fetch-upstream-resources.sh script as an environment variable,
# so that they are persisted in the image for use in later stages.
ARG ENGINE_BRANCH
ENV ENGINE_BRANCH=${ENGINE_BRANCH}

ARG DISTRIBUTION_BRANCH
ENV DISTRIBUTION_BRANCH=${DISTRIBUTION_BRANCH}


# Empty stage if archives are disabled (ENABLE_ARCHIVES=false)
FROM scratch AS archives-false

# Stage with static HTML for all archives (ENABLE_ARCHIVES=true)
FROM scratch AS archives-true
ENV TARGET=/usr/share/nginx/html
# To add a new archive, add it here and ALSO edit _data/docsarchive/archives.yaml
# to add it to the drop-down
COPY --from=docs/docker.github.io:v17.06 ${TARGET} /
COPY --from=docs/docker.github.io:v18.03 ${TARGET} /
COPY --from=docs/docker.github.io:v18.09 ${TARGET} /

# Stage either with, or without archives, depending on ENABLE_ARCHIVES
FROM archives-${ENABLE_ARCHIVES} AS archives

# Fetch upstream resources (reference documentation)
# Only add the files that are needed to build these reference docs, so that these
# docs are only rebuilt if changes were made to ENGINE_BRANCH or DISTRIBUTION_BRANCH.
# Disable caching (docker build --no-cache) to force updating these docs.
FROM alpine AS upstream-resources
RUN apk add --no-cache subversion wget
WORKDIR /usr/src/app/md_source/
COPY ./_scripts/fetch-upstream-resources.sh ./_scripts/
ARG ENGINE_BRANCH
ARG DISTRIBUTION_BRANCH
RUN ./_scripts/fetch-upstream-resources.sh .


# Build the static HTML for the current docs.
# After building with jekyll, fix up some links, but don't touch the archives
FROM builderbase AS current
COPY . .
COPY --from=upstream-resources /usr/src/app/md_source/. ./
# substitute the "{site.latest_engine_api_version}" in the title for the latest
# API docs, based on the latest_engine_api_version parameter in _config.yml
RUN ./_scripts/update-api-toc.sh
RUN jekyll build -d ${TARGET} \
&& find ${TARGET} -type f -name '*.html' | grep -vE "v[0-9]+\." | while read i; do sed -i 's#href="https://docs.docker.com/#href="/#g' "$i"; done


# This stage only contains the generated files. It can be used to host the
# documentation on a non-containerised service (e.g. to deploy to an s3 bucket).
# When using BuildKit, use the '--output' option to build the files and to copy
# them to your local filesystem.
#
# To build current docs, including archives:
# DOCKER_BUILDKIT=1 docker build --target=deploy-source --output=./_site .
#
# To build without archives:
# DOCKER_BUILDKIT=1 docker build --target=deploy-source --build-arg ENABLE_ARCHIVES=false --output=./_site .
FROM archives AS deploy-source
COPY --from=current /usr/share/nginx/html /

# Final stage, which includes nginx, and, depending on ENABLE_ARCHIVES, either
# current docs and archived versions (ENABLE_ARCHIVES=true), or only the current
# docs (ENABLE_ARCHIVES=false).
#
# To build current docs, including archives:
# DOCKER_BUILDKIT=1 docker build -t docs .
#
# To build without archives:
# DOCKER_BUILDKIT=1 docker build -t docs --build-arg ENABLE_ARCHIVES=false .
FROM nginx:alpine AS deploy
ENV TARGET=/usr/share/nginx/html
WORKDIR $TARGET

COPY --from=archives / .
COPY --from=current /usr/share/nginx/html .

# Configure NGINX
COPY _deploy/nginx/default.conf /etc/nginx/conf.d/default.conf
CMD echo -e "Docker docs are viewable at:\nhttp://0.0.0.0:4000"; exec nginx -g 'daemon off;'

我的.drone.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
---
kind: pipeline
type: docker
name: docker.github.io

workspace:
path: /build/docker.github.io

platform:
os: linux
arch: arm


steps:
- name: docker
image: plugins/docker
settings:
repo: 10.10.100.12:5000/docker.github.io
tags: latest
insecure: true
registry: 10.10.100.12:5000
custom_dns: 114.114.114.114
...

最后

最后我共享下我编译出来的镜像

docker pull bboysoul/docker.github.io:19.03

因为docker文档的内容比较大,所以整体会比较大

已运行的网址

docker.bboysoul.cn

欢迎关注Bboysoul的博客www.bboy.app

Have Fun

欢迎关注我的其它发布渠道