Docker 菜鸟视角 -- 用 Dockerfile 构建测试环境 (镜像包括 python chrome 浏览器 解决中文乱码问题)

徐旻 · May 08, 2017 · Last by 白纸 replied at December 27, 2017 · 2454 hits

前一次我们通过 docker 搭建了 selenium 的分布式测试环境。
在学习过程中,觉得如果把调试环境也放在 docker,这样不管以后在工作中统一大家的调试的测试环境肯定会有帮助的。
刚开始我觉得只要我把我配置好的环境做成一个 images 然后发给需要的人,让他们导入到 docker 中就可以了。
但是这个方法看起来很笨重,也不利于镜像的管理,如果镜像里修改了某些内容,难道还让我把新的镜像在发放一次?
答案是这个方法可行,但是还是笨重。
好在 docker 有自己的管理方式,就是 dockerfile。
工作原理很简单,dockerfile 中先指定一个基础镜像,然后把 shell 命令写到脚本中,然后脚本根据内容,在基础镜像的上开始运行脚本,最后就生成了新的镜像。
这种方式的好处就我现在能感受到的优点有:
1.方便传送,一个 dockerfile 基本上不会大于 1M,但是一个 docker image 有的却会是几百 M 以上的。
2.方便维护,当我们的 images 中需要删除,或者增加什么工具或者控件的时候,我们修改 dockerfile,然后发布出去,大家重新构建 images 就可以了。不需要去通知每个人去做操作,或者去每个人的 images 中去做相同的操作。

那么我们开始学习 dockerfile。

目标:在镜像 selenium/standalone-chrome-debug 中添加 python 和中文字体。

1.问题

首先我们看下图

上图是我启动容器 debug(使用的镜像 selenium/standalone_chrome_debug),首先我们发现没有安装 python,其次打开的网页中中文显示为乱码。我们就遇上了两个问题
问题 1:安装 python
问题 2:增加字库

增加字库,解决方案

下图是@ycwdaaaa 在文章https://testerhome.com/topics/8450 中给出一个解决方案。他建议在 dockerfile 中加入以下命令

前面我说了 dockerfile 中其实很大一部分就是执行 shell 命令。
那么我们来验证下,在容器 debug 的 bash 中输入命令
apt-get update
apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei
重新打开浏览器,发现中文乱码已经解决,不但问题解决了,还证明只要会 shell 命令,dockerfile 的配置还是很简单的。

那我们开始编写 dockfile 然后构建我们需要的镜像。

FROM selenium/standalone-chrome-debug:3.4.0


USER root

RUN apt-get update \
    && apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei \
    && apt-get clean

我们来分析下这段 dockfile 的内容
1.FROM selenium/standalone-chrome-debug:3.4.0
从一个基础镜像开始建立我们的新镜像 这里把 selenium/standalone-chrome-debug:3.4.0 作为基础镜像

2.USER root
没有取查,估计意思是给 root 权限吧。

3.RUN apt-get update \
&& apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei \
&& apt-get clean
RUN 是 dockerfile 中的一个命令就是运行
然后先运行命令
apt-get update
看看 apt-get 的是否有更新
在运行命令
apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei
用 apt-get 命令安装字库
最后运行命令
apt-get clean

那么来运行 dockerfile 来构建,输入命令
docker build -t debug/chinese .
这里我们要注意,好像运行 docker build 的时候是自动寻找当前目录下的 dockerfile,所以,我们先要进入到需要运行 dockerfile 的目录下才运行改命令。
如果 build 顺利,我们应该在 images 命令中找到新构建的镜像 debug/chinese

然后我们启动该镜像

然后用 vnc 链接到容器内部。

打开 chrome 浏览区,输入百度的首页,我们就看到新构建的镜像启动出来的容器中的浏览器是没有中文乱码的困惑的。

Ps:注意,构建的时候一定要注意网络状态,我家网络太差了,构建的时候经常失败,构建了 4 个小时,才成功的。失败的时候,也会产生 image,但是是没有 repository 名和 tag 名的,还会启动一个容器。我们需要先去杀掉容器,docker rm 命令,在删除构建失败的镜像 docker rmi 命令。

添加 python 系统,解决方案

通过字库的解决方案,我们了解到了 dockerfile 如何使用的。
让我现在写 shell 去安装不可能,作为一个有善于思考的伸手党。
我在 github 上找到了 docker-python 的 dockerfile
https://github.com/docker-library/python/blob/db2d58d73043c85ceecc8e675372b4dc6a77d136/2.7/Dockerfile
我觉得只要把这个 dockerfile 中
FROM buildpack-deps:jessie 修改为 FROM selenium/standalone-chrome-debug:3.4.0
然后构建就应该成功。我现在就在构建中,无奈家中网络太差,一直构建到一半就失败。不过只要网络好,应该不会有问题的。

当然我们也可以做的细致点。把官方的 dockerfile 分解一下。
其实官方的 dockerfile 完成了 3 个内容。
1.安装 python
2.安装 PIP
3.安装 virtualenv

还有一些安装依赖。
所以,我打算先做一个 dockerfile,不安装 pip,virtualenv,只安装 python。然后构建成功的镜像在用新的 dockerfile(chrome_debug + python)去构建一个 PIP 的的镜像。

FROM selenium/standalone-chrome-debug:3.4.0

# ensure local python is preferred over distribution python
ENV PATH /usr/local/bin:$PATH

ENV LANG en_US.UTF-8

# runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        tcl \
        tk \
    && rm -rf /var/lib/apt/lists/*


RUN apt-get update \
    && apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei \
    && apt-get clean

RUN apt-get update && apt-get install -y build-essential

ENV GPG_KEY C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF
ENV PYTHON_VERSION 2.7.13

RUN set -ex \
    && buildDeps=' \
        tcl-dev \
        tk-dev \
    ' \
    && apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* \
    \
    && wget -O python.tar.xz "https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz" \
    && wget -O python.tar.xz.asc "https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tar.xz.asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \
    && gpg --batch --verify python.tar.xz.asc python.tar.xz \
    && rm -r "$GNUPGHOME" python.tar.xz.asc \
    && mkdir -p /usr/src/python \
    && tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \
    && rm python.tar.xz \
    \
    && cd /usr/src/python \
    && ./configure \
        --enable-shared \
        --enable-unicode=ucs4 \
    && make -j "$(nproc)" \
    && make install \
    && ldconfig \
    \
    && apt-get purge -y --auto-remove $buildDeps \
    \
    && find /usr/local -depth \
        \( \
            \( -type d -a -name test -o -name tests \) \
            -o \
            \( -type f -a -name '*.pyc' -o -name '*.pyo' \) \
        \) -exec rm -rf '{}' + \
    && rm -rf /usr/src/python

这个 dockerfile 其实就是把 python 的 dockerfile 拿过来然后把镜像源该成了
FROM selenium/standalone-chrome-debug:3.4.0

当中要注意两点
1.RUN apt-get update \
&& apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei \
&& apt-get clean
这段就是我们前面说的添加中文字体

2.RUN apt-get update && apt-get install -y build-essential
这句花了我一天的时间调查,如果没有这句,就会报错,看下图。

造成这个错误的原因就是 selenium 的镜像里没有装好 gcc,但是 python 的镜像里是装好 gcc 的。
安装 python 本身没有问题,但是安装依赖缺失了。所以要在这里补这么一句。

然后运行 dockerfile,等新的镜像做成,然后启动容器。

我们看到了带有 python 的可以显示中文的一个 调试环境。

总结

我们可以不会写 shell,但是要会看的懂 shell,简单的操作命令百度一下什么都有了。
当 dockerfile 构建报错的时候,先去看 logs,然后把报错的那句命令 拆分开(如果是多个命令在一起的比如很多时候 apt-get 的命令是用&&连接的。)去 docker 容器内调试看看。
尽量去找官方已经做好的 dockerfile,然后微调一下。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 6 条回复 时间 点赞

首先说一下 USER 这个指令哈。USER 的意思是工作用户。 是说用哪个用户执行下面的命令。你的例子里面就是用 root 用户执行下面的命令,并且容器启动以后,entrypoint 和 CMD 都是用 root 去执行的。 用 docker exec 命令进入容器的里面也是 root 用户。 如果换了另一个用户,例如 work。 你再用 docker exec 命令进去容器的时候就会发现当前使用的用户是 work 了。类似的还有 WORKDIR 这个指令。意思是工作目录。

再说就是楼主说的镜像的共享的问题。楼主主要是通过 dockerfile 来达到镜像共享的问题。他人通过拿到你的 dockerfile 重新 build 一个镜像的方式来使用。其实我是十分不推荐这种做法的。 楼主可能觉得一个镜像比较大,传递起来比较麻烦耗时。 但是有些时候重新 build 一个镜像是更耗时的。尤其是这个镜像有好几层的时候。或者 dockerfile 里写了很多安装工具的 shell,例如安装一个 jdk 就比较耗时。我这里有一个编译的基本镜像。从 gcc 到 thrift 到 jdk 到 scala 应有尽有,build 这么个镜像没半个小时一个小时的是结束不了的。这时候反倒是拉现有的镜像比较快。 而且重新 build 一个镜像的话你是控制不了对方给这个镜像起什么名字,用什么 tag 的。非常的不好管理。 有时候会造成一个机器里同一个镜像有好多个名字和 tag 的情况。

所以我比较建议楼主在内网搭建一个镜像仓库。build 好一个镜像以后直接 push 上去。 别人想用的话直接拉下来就好了。 不用你主动的发包给他。你只要维护好镜像仓库上的镜像版本就好了。有点像你在内网搭建了一个 docker hub 的感觉。 在以后测试环境变多,docker 单节点扩展到多节点。 引入编排工具的时候,例如我用的 k8s。 在多个节点之间共享镜像用的也同样是镜像仓库。 这类的容器编排工具都会提供 image pull policy。通过你选择的策略去决定是否从镜像仓库中重新拉取最新的镜像。

楼主,我启动了中文的镜像,为什么显示中文还是乱码?

今天在家重新试过,用 dokcerfile 报错如下:

  Hash Sum mismatch
E: Failed to fetch http://211.162.127.22/files/4161000000808046/mirrors.163.com/debian/pool/main/f/fonts-wqy-microhei/fonts-wqy-microhei_0.2.0-beta-2_all.deb  Hash Sum mismatch

E: Fetched 9,073 kB in 15s (580 kB/s)
Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
The command '/bin/sh -c apt-get update     && apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei     && apt-get cleani' returned a non-zero code: 100
root@default:/mnt/sda1/tmp# 

我的 dockerfile:

FROM selenium/standalone-chrome-debug:3.4.0

USER root

RUN apt-get update \
    && apt-get -y install ttf-wqy-microhei ttf-wqy-zenhei \
    && apt-get clean

家里长城宽带问题。。。

上次用你的方式被隔壁的人教育说用 Shell 脚本是错误的

@lunamagic 请问 vnc 连接后,root 密码是什么

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up