使用 Docker 构建工作环境

1. 前言

作为一个程序员,在家加班或者处理紧急需求是一种常态。为了应对这种情况(也为了更好地压榨程序员的剩余时间)大部分公司都会给员工配发笔记本电脑。

新员工入职第一件事情就是配置工作环境,这个工作至少耗费一天的时间。有经验的程序员一般会用一个 dotfile 项目来保存常用的配置文件,比如 .zshrc.vimrc.ssh/config 等。

本文更进一步,使用 Docker 来构建工作环境。

原因在于以下几个方面:

  • 任意电脑都可以快速初始化工作环境。本人不喜欢把公司电脑背回家,一来太重太麻烦,而来丢了坏了还要找你赔。

  • 隔离工作环境。把工作环境当做不同的 profile,以插件的形式加载到环境中,灵活而且干净。

2. 实施方案

为了更好地保障安全性,本人把工作环境的 Docker 分为两个部分:

  • Docker 镜像

  • dotfile (Git 仓库)

本质上是代码和配置分离的策略,镜像可以使用阿里云提供的服务来存储,而 Dockerfile 和 dotfile 则利用 Git 的私有库做版本控制和多机器同步。

2.1 Docker 镜像

以下是本人人生中第一个 Dockerfile:

 ARG UBUNTU_VERSION=18.04
 FROM ubuntu:${UBUNTU_VERSION}
 MAINTAINER wuzhiyu "wuzhiyu@avalon-inc.com"
 
 ###################### SYSTEM SETTINGS ######################
 
 ARG USER_NAME=<account name>
 ARG GROUP_NAME=sudo
 ARG PASSWORD=<password>
 ARG HOME=/home/${USER_NAME}
 ARG HOST_NAME=ubuntu-docker
 
 # 1. update chinese software repository
 RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak
 COPY 18.04.aliyun.sources.list /etc/apt/sources.list
 
 # 2. install necessary software
 ENV DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y sudo man curl inetutils-ping git tmux vim autojump python-pip zsh oathtool expect && apt-get clean && pip install mycli virtualenv virtualenvwrapper
 RUN apt-get update && apt-get install -y locales && apt-get clean && locale-gen en_US.UTF-8
 
 # 3. (1)create a user account without password (2) grant sudo permission by adding account to sudo group (3) set password for the account
 
 RUN adduser --home ${HOME} --ingroup ${GROUP_NAME} --shell /bin/bash --disabled-password --gecos "" ${USER_NAME} && echo "${USER_NAME}:${PASSWORD}" | chpasswd
 RUN chown -R ${USER_NAME}:${GROUP_NAME} ${HOME}
 
 ###################### USER SETTINGS ######################
 
 # set default user and work dir
 USER ${USER_NAME}
 WORKDIR ${HOME}
 ENV USER ${USER_NAME}
 
 # install oh-my-zsh
 RUN export RUNZSH=yes && sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
 
 # config-files -v when docker run
 
 # CMD
 CMD /usr/bin/zsh

这个 Dockerfile 干的事情非常简单,简单来说就是:

  1. 指定基础镜像。

  2. 更新 Ubuntu 的软件源。国情在此,用阿里云的替换。

  3. 使用非交互模式安装必要的软件。

  4. 创建用户账户并授予 sudo 的权限。

  5. 切换到用户账户和家目录。

  6. 安装 oh-my-zsh

  7. 指定默认进入 zsh

构建命令为:

 docker build -t workspace:latest ubuntu

其中 ubuntu 是保存 Dockerfile 和其他文件的上下文目录。

看的出来镜像本身是比较简单的,主要是准备必要的软件和运行账户,下面来介绍一下 dotfile。

2.2 dotfile

dotfile 项目包括不限于以下内容:

  • .zshrc

  • .vimrc

  • .ssh/config

  • 公钥私钥

  • 业务脚本

2.2.1 .zshrc

这个文件是 zshell 启动时默认加载的文件,一般也是我们所有环境配置的公共部分。我们可以通过一些命令来判断加载特定的 profile。

比如:

 # 为 true 表示为 Mac 环境
 [[ $(uname) = "Darwin" ]]
 
 # 为 true 表示为 Docker 环境
 [[ -f /.dockerenv ]]

如果为 docker 环境,我们可以 source 包含业务信息的脚本(比如自动进行两步校验的登录脚本、包含数据库连接串信息的脚本等等),也可以进行环境配置文件的自动更新。

2.2.2 .vimrc

Vim 的配置文件,此处不表。

2.2.3 .ssh/config

常见来说两种使用功能:

  • 自动指定跳板机或端口信息

  • 对应特定应用使用特定私钥

首先一般公司内部连接线上服务器都要求通过指定的跳板机和特定端口(非默认 22)来连接,每次指定自然非常繁琐,通过 .ssh/config 文件则可以大大减轻负担。

 Host *.dev
     HostName %h.xxx.com
     User wuzhiyu
     Port 10086
     ProxyJump <gateway>
     IdentityFile <path_to_private_key>

一般来说,如果我们要连接 master01.dev.xxx.com 这台机器一般要先跳到跳板机,然后使用如下命令:

 ssh -i <path_to_private_key> wuzhiyu@master01.dev.xxx.com -p 10086

但是有了上述配置,我们可以写作:

 ssh master01.dev

跳板机、端口、机器后缀、私钥位置自动带上了。

2.2.4 公钥私钥

接上文,对于不同的版本控制系统使用不同的密钥是很常见的一种场景。比如公司内部用一套密钥,个人 GitHub 账户使用另外一套,把公司的密钥放在 dotfile 私有库进行同步便于配置的保存与迁移。

2.2.5 业务脚本

比如数据库连接串的别称、自动登录脚本等,不再赘述。

3. 实践使用

Docker 运行的时候可以使用如下命令进行启动:

 docker run -it --rm -h docker --network host -v <path_to_dotfile_dir>:/home/wuzhiyu/.config-files:ro -v <path_to_zshrc_file>:/home/wuzhiyu/.zshrc:ro --name workspace workspace:latest /usr/bin/zsh

这里有几点要注意:

  1. 网络模式使用了 -—network host 模式是为了使用宿主机的 VPN 网络。

  2. 加载的时候直接挂在了 .zshrc 文件,这样容器运行 zshell 的时候就可以直接加载初始化的脚本。

  3. 默认指定一下 HOST 名称否则部分软件运行会报错。