如何制作和使用GitLab的Docker镜像

虽然GitLab提供了官方的Docker镜像,但是并没有实现中文化,本文将基于官方的Dockerfile和配置脚本,整合GitLab中文社区的汉化包,介绍如何制作和使用中文版的GitLab镜像。

PS:本来打算以自建的CentOS 6.9镜像为基础构建GitLab镜像,这样就能实现完全自定义的GitLab镜像,但是在安装RPM包时遇到ruby_block[supervise_redis_sleep] action run的问题,导致安装进程卡死,目前尚未找到解决方案,因此本文决定基于官方的Dockerfile构建镜像。

一、环境描述

1. 虚拟机配置

  • CPU:双核
  • 内存:4 GB
  • 硬盘:120 GB
  • IP:192.168.190.128

2. 操作系统

  • 版本:CentOS 7.4 x86_64 (1708)
  • 安装方式:Minimal

3. Docker

4. GitLab

  • 版本:GitLab CE 10.5.3
  • 安装方式:OmniBus

二、下载omnibus-gitlab工程

在shell中运行以下命令,安装git和wget软件包,然后下载官方的omnibus-gitlab工程:

yum install -y git wget
cd /root/Downloads
git clone https://gitlab.com/gitlab-org/omnibus-gitlab.git

三、下载GitLab汉化工程

在shell中运行以下命令,下载GitLab中文社区的汉化工程:

git clone https://gitlab.com/xhang/gitlab.git

四、下载GitLab安装包

在shell中运行以下命令,下载deb格式的安装包:

wget --content-disposition https://packages.gitlab.com/gitlab/gitlab-ce/packages/ubuntu/xenial/gitlab-ce_10.5.4-ce.0_amd64.deb/download.deb /root/Downloads/gitlab-ce_10.5.4-ce.0_amd64.deb

五、配置构建环境

1. 打包汉化工程

将下载得到的汉化工程打包为tar.gz压缩包:

tar cvzf gitlab.tar.gz gitlab

2. 拷贝安装包和汉化包

将GitLab的安装包和汉化包拷贝至Dockerfile的所在目录:

cp gitlab-ce_10.5.4-ce.0_amd64.deb omnibus-gitlab/docker/
cp gitlab.tar.gz omnibus-gitlab/docker/

3. 新增RELEASE文件

GitLab的omnibus-gitlab工程中缺少RELEASE文件,而这个文件又包含构建镜像需要的环境变量。我从GitLab的官方镜像中提取出这个文件,然后自己新建RELEASE文件:

cd omnibus-gitlab/docker
vi RELEASE

上述文件的内容如下所示:

PACKAGECLOUD_REPO=gitlab-ce
RELEASE_PACKAGE=gitlab-ce
RELEASE_VERSION=10.5.4-ce.0
DOWNLOAD_URL=https://downloads-packages.s3.amazonaws.com/ubuntu-xenial/gitlab-ce_10.5.4-ce.0_amd64.deb

不会使用DOWNLOAD_URL变量,因为本文会使用上文通过wget下载的安装包。

4. 修改Dockerfile文件

编辑Dockerfile文件:

vi Dockerfile

上述文件修改后的内容,如下所示:

FROM ubuntu:16.04
MAINTAINER GitLab Inc. <support@gitlab.com>

SHELL ["/bin/sh", "-c"],

# Install required packages
RUN apt-get update -q \
    && DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
      ca-certificates \
      openssh-server \
      wget \
      apt-transport-https \
      vim \
      tzdata \
      nano \
      patch \
      git \
    && rm -rf /var/lib/apt/lists/* \
    && sed 's/session\s*required\s*pam_loginuid.so/session optional pam_loginuid.so/g' -i /etc/pam.d/sshd

# Remove MOTD
RUN rm -rf /etc/update-motd.d /etc/motd /etc/motd.dynamic
RUN ln -fs /dev/null /run/motd.dynamic

# Copy assets
COPY RELEASE /
COPY assets/ /assets/
COPY gitlab.tar.gz /
COPY gitlab-ce_10.5.4-ce.0_amd64.deb /tmp/gitlab.deb
RUN /assets/setup

# Allow to access embedded tools
ENV PATH /opt/gitlab/embedded/bin:/opt/gitlab/bin:/assets:$PATH

# Resolve error: TERM environment variable not set.
ENV TERM xterm

# Expose web & ssh
EXPOSE 443 80 22

# Define data volumes
VOLUME ["/etc/gitlab", "/var/opt/gitlab", "/var/log/gitlab"]

# Wrapper to handle signal, trigger runit and reconfigure GitLab
CMD ["/assets/wrapper"]

HEALTHCHECK --interval=60s --timeout=30s --retries=5 \
CMD /opt/gitlab/bin/gitlab-healthcheck --fail

主要有以下修改点:

  • 第16~17行:在apt-get命令处新增下载和安装patch和git软件包;
  • 第28~29行:拷贝汉化包和安装包至临时容器。

5. 新增translation脚本

这个脚本负责解压汉化包,然后生成用于汉化的diff补丁文件,最后给GitLab打汉化补丁。创建translation脚本:

cd assets
vi translation

上述脚本的内容如下所示:

#!/bin/bash

tar xvf gitlab.tar.gz
cd gitlab
gitlab_version=$(cat /opt/gitlab/embedded/service/gitlab-rails/VERSION)
git diff v${gitlab_version} v${gitlab_version}-zh > ../${gitlab_version}-zh.diff
gitlab-ctl stop
patch -d /opt/gitlab/embedded/service/gitlab-rails -p1 < /${gitlab_version}-zh.diff
cd ..
rm -rf gitlab ${gitlab_version}-zh.diff gitlab.tar.gz

保存退出之后,修改脚本的权限:

chmod 755 translation

6. 修改setup脚本

编辑setup脚本:

vi setup

上述文件修改后的内容,如下所示:

#!/bin/bash

set -e

source /etc/lsb-release
source /RELEASE

# Install GitLab
dpkg -i /tmp/gitlab.deb && rm /tmp/gitlab.deb
rm -rf /var/lib/apt/lists/*

# translate to chinese
/assets/translation

# Create sshd daemon
mkdir -p /opt/gitlab/sv/sshd/supervise /opt/gitlab/sv/sshd/log/supervise
mkfifo /opt/gitlab/sv/sshd/supervise/ok /opt/gitlab/sv/sshd/log/supervise/ok
printf "#!/bin/sh\nexec 2>&1\numask 077\nexec /usr/sbin/sshd -D -f /assets/sshd_config -e" > /opt/gitlab/sv/sshd/run
printf "#!/bin/sh\nexec svlogd -tt /var/log/gitlab/sshd" > /opt/gitlab/sv/sshd/log/run
chmod a+x /opt/gitlab/sv/sshd/run /opt/gitlab/sv/sshd/log/run
mkdir -p /var/run/sshd

# Remove current gitlab.rb file
rm -f /etc/gitlab/gitlab.rb

# Patch omnibus package
sed -i "s/external_url 'GENERATED_EXTERNAL_URL'/# external_url 'GENERATED_EXTERNAL_URL'/" /opt/gitlab/etc/gitlab.rb.template
sed -i "s/\/etc\/gitlab\/gitlab.rb/\/assets\/gitlab.rb/" /opt/gitlab/embedded/cookbooks/gitlab/recipes/show_config.rb
sed -i "s/\/etc\/gitlab\/gitlab.rb/\/assets\/gitlab.rb/" /opt/gitlab/embedded/cookbooks/gitlab/recipes/config.rb

# Create groups
groupadd -g 998 git
groupadd -g 999 gitlab-www
groupadd -g 997 gitlab-redis
groupadd -g 996 gitlab-psql

groupadd -g 994 mattermost
groupadd -g 993 registry
groupadd -g 992 gitlab-prometheus
groupadd -g 991 gitlab-consul

# Create accounts
useradd -m -u 998 -g git -m -s /bin/sh -d /var/opt/gitlab git
useradd -m -u 999 -g gitlab-www -m -s /bin/false -d /var/opt/gitlab/nginx gitlab-www
useradd -m -u 997 -g gitlab-redis -m -s /bin/false -d /var/opt/gitlab/redis gitlab-redis
useradd -m -u 996 -g gitlab-psql -m -s /bin/sh -d /var/opt/gitlab/postgresql gitlab-psql
useradd -m -u 994 -g mattermost -m -s /bin/sh -d /var/opt/gitlab/mattermost mattermost
useradd -m -u 993 -g registry -m -s /bin/sh -d /var/opt/gitlab/registry registry
useradd -m -u 992 -g gitlab-prometheus -m -s /bin/sh -d /var/opt/gitlab/prometheus gitlab-prometheus
useradd -m -u 991 -g gitlab-consul -m -s /bin/sh -d /var/opt/gitlab/consul gitlab-consul

主要有以下修改点:

  • 第9行:删除download-package脚本的调用,直接安装上文下载的GitLab安装包;
  • 第12~13行:调用translation脚本。

六、构建GitLab镜像

在shell中运行以下命令,构建GitLab的Docker镜像:

cd ..
docker build -t gitlab-zh:10.5.4 .

构建完成之后,检查镜像信息,若如下图所示,则表示构建正确:

检查GitLab镜像

七、启动GitLab容器

1. 数据目录

GitLab容器会使用宿主机挂载的卷或目录来存储持久化数据,本文使用的目录,如下表所示:

宿主机目录 容器目录 用途
/usr/local/gitlab/data /var/opt/gitlab 用于存储应用数据
/usr/local/gitlab/logs /var/log/gitlab 用于存储日志
/usr/local/gitlab/config /etc/gitlab 用于存储GitLab的配置文件

在shell中运行以下命令,建立数据目录:

mkdir -p /usr/local/gitlab/data
mkdir -p /usr/local/gitlab/logs
mkdir -p /usr/local/gitlab/config

请根据实际情况调整这些目录的配置。

2. 预配置环境变量

在运行docker run命令时,你可以添加GITLAB_OMNIBUS_CONFIG环境变量,这样便能对GitLab的Docker镜像进行预配置。这个变量可以包含gitlab.rb文件中的任何配置项,相比起gitlab.rb文件,容器会优先加载这个变量中的配置项。通过这种方式,你便可以轻松地配置GitLab的外部URL、数据库的任何配置,或者其他Omnibus GitLab配置文件模板中包含的配置项。

本文会设置以下配置项:

2.1 外部URL
external_url "http://192.168.190.128"

请根据实际情况调整外部URL的配置。

2.2 邮件提醒
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.exmail.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "example@example.com"
gitlab_rails['smtp_password'] = "example_password"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = 'example@example.com'

本文使用腾讯企业邮箱,GitLab会通过上面的SMTP配置给用户发送通知邮件,请根据实际情况调整SMTP的配置。

3. 启动命令

综合上文描述的数据目录和预配置环境变量,本文使用的容器启动命令,如下所示:

docker run --detach \
    --name gitlab \
    --hostname gitlab \
    --env GITLAB_OMNIBUS_CONFIG="external_url 'http://192.168.190.128/'; gitlab_rails['smtp_enable'] = true; gitlab_rails['smtp_address'] = 'smtp.exmail.qq.com'; gitlab_rails['smtp_port'] = 465; gitlab_rails['smtp_user_name'] = 'example@example.com'; gitlab_rails['smtp_password'] = 'example_password'; gitlab_rails['smtp_authentication'] = 'login'; gitlab_rails['smtp_enable_starttls_auto'] = true; gitlab_rails['smtp_tls'] = true; gitlab_rails['gitlab_email_from'] = 'example@example.com';" \
    --publish 443:443 --publish 80:80 \
    --restart always \
    --volume /usr/local/gitlab/config:/etc/gitlab \
    --volume /usr/local/gitlab/logs:/var/log/gitlab \
    --volume /usr/local/gitlab/data:/var/opt/gitlab \
    gitlab-zh:10.5.4

上述命令各个选项的具体用途,本文不再赘述,请参考docker run命令的参考文档。

八、验证

GitLab容器需要几分钟才能把所有的服务启动完成,在此期间,系统页面一直是不能访问的状态。

1. 检查服务状态

在shell中运行以下命令,检查GitLab服务状态:

docker exec -it gitlab gitlab-ctl status

若上述命令的输出信息如下图所示,则表示服务启动完成:

检查GitLab服务状态

2. 访问GitLab

在浏览器中访问以下URL:

http://192.168.190.128

首次访问GitLab时,会要求设置新的管理员密码,如下图所示:

设置管理员密码

管理员密码设置完成之后,就会跳转至登录/注册页面。默认的管理员账号是admin@example.com,输入管理员账号和密码之后,就会跳转到GitLab的首页,如下图所示:

GitLab登录后首页

至此,GitLab的Docker镜像已经制作完成,并且在宿主机上简单地启动了一个容器实例!

附录

GitLab的Docker镜像也是基于OmniBus的安装方式制作的,这种方式会将运行GitLab需要的所有服务和工具打包至一个安装包之中,使得大多数用户不用再经历繁琐和枯燥的配置过程。GitLab的系统架构,如下图所示:

GitLab系统架构