menu

Docker

推荐阅读 Docker —— 从入门到实践 · GitBook,了解镜像、容器、仓库的概念。

对象底层原理有兴趣推荐阅读陈皓的 Docker 系列文章,可以一窥 Docker 的实现原理。

安装 Docker

  • 开发环境:Arch Linux
  • 服务器:openSuse leap 42.1 Arch 和 openSuse 的官方源都有 docker ,安装很简单

Arch :

$ sudo pacman -S docker

openSuse:

$ sudo zypper in docker

两个系统都是 systemd,配置服务命令也一模一样

开启服务:

$ sudo systemctl start docker

配置开机自启动:

$ sudo systemctl enable docker

具体安装步骤可看官方文档

OSX

使用 [Docker For Mac][https://docs.docker.com/docker-for-mac/]

配置 gitlab

gitlab 官方也提供了 docker 镜像,安装过程很简单,一句命令搞定。可见 GitLab Documentation

sudo docker run --detach \
        --hostname gitlab \
        --publish 443:443 --publish 80:80 --publish 2222:22 \ # 将 22 端口映射到 2222 主要是不要干扰 host 本身的 22 端口
        --name gitlab \
        --restart always \
        --volume /srv/gitlab/config:/etc/gitlab \
        --volume /srv/gitlab/logs:/var/log/gitlab \
        --volume /srv/gitlab/data:/var/opt/gitlab \
        gitlab/gitlab-ce:latest

在 OSX 中,可将 /srv 替换为 /Users/Shared

Docker Hub 镜像

run 命令,首先将会下载 gitlab-ce 镜像(本地没有的话),后在本地建立新容器并运行。Docker Hub 的下载速度堪忧,可用国内的镜像(register-mirror)替换。我选择的是阿里云的加速器。使用 systemd 的话,需在 /etc/systemd/system/docker.service.d/mirror.conf 写入

[Service] 
ExecStart= 
ExecStart=/usr/bin/docker daemon -H fd:// --registry-mirror=https://{id}.mirror.aliyuncs.com

覆盖掉默认的 docker 启动命令。可参考阿里云的文档。顺便八卦下为什么 ExecStart 要先赋空值,见 systemd - ArchWiki

网络

--detach 让容器启动后在后台运行,相对应的 docker 还有 attach 命令,让容器的启动进程附加到当前终端上。但由于容器的启动进程 pid 为 1,强制杀死的信号对它没有用,也就是说 Ctrl-c 也不能强制中断当前进程,Docker 提供了个快捷键用来让容器重新回到后台:Ctrl-p, Ctrl-q,但是我在 konsole 上这个快捷键没有效,可能是因为 Ctrl-p 绑定了上一行功能,所以只能关掉标签页了事。

--hostname 建议设置,我设置为 gitlab,因为容器内的 ip 段是 172.17.0.*,不同于外部 ip,设置 hostname 更灵活,而后可在其他容器或主机配置 /etc/hosts 来设置具体 ip。

--publish 2222:22 把容器的 22 端口映射到主机的 2222 端口,不和默认的 sshd 服务端口冲突。

gitlab/gitlab-ce:latest 就是镜像。

容器启动完毕,容器将在后台启动 gitlab 相关服务。

$ sudo docker logs gitlab

可以打印出容器的日志输出。通过 dockerfile 可知道实际跑的是/usr/local/bin/wrapper 这个脚本,也可以手动执行这个脚本来启动服务。等待几分钟 gitlab 启动就完毕了。

最后,在主机的 /etc/hosts 加上这条记录

127.0.0.1    gitlab

便可以在本机通过 http://gitlab 访问,就这么简单一条命令部署好整个环境。

如果不绑定域名,直接使用 IP 访问的话,可能需要修改 /etc/gitlab/gitlab.rb

external_url 'http://IP[:PORT]'  # 如 http://192.168.x.x:6080 能让 gitlab-runner 访问到的地址

然后运行 gitlab-ctl reconfigure。不然 gitlab-runner 用的是默认的外部地址,可能导致 clone 失败,见 issues 1977 和 https://stackoverflow.com/a/28005168/851344

配置 gitlab-runner

gitlab-runner 的安装也很简单:

docker run -d --name gitlab-runner --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest

安装好后,先进入 bash 配置环境,

$ sudo docker exec -it gitlab-runner /bin/bash

网络

首先 /etc/hosts 加上这条记录

172.17.0.1    gitlab

将 gitlab 指向主机,试试看下面指令能否成功:

$ curl http://gitlab

如果不能访问,也可以直接指向 gitlab 容器,可以通过获取到 gitlab 容器的 ip:

$ sudo docker inspect gitlab

安装之后,便需要注册 gitlab-runner。当然要跑起来之前,还需要配置 Android 环境和.gitlab-ci.yml 脚本。

可以遇到 bash - how to remove “TERM environment variable not set” - Stack Overflow

配置 Android 环境

接下来安装 android sdk 和 gradle 的依赖。gitlab-runner 基于 Ubuntu 14.04,下面命令可打印出系统版本:

$ cat /etc/issue 

建议配置网易 Ubuntu 镜像,可以 docker cp 命令将外部文件拷入容器:

$ sudo docker cp  ~/Downloads/sources.list.trusty gitlab-runner:/etc/apt/sources.list.trusty

接着用 apt-get 下载依赖,这里使用的是 jdk7

$ apt-get -qq update && apt-get install -qqy --no-install-recommends curl html2text openjdk-7-jdk libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5 lib32z1 unzip && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

如果项目用了 lambda 或其他需要 jdk8 支持的特性,那么就需要安装 jdk8 了,见 https://stackoverflow.com/a/32944272/851344

Build Tools

环境搭好后,便可以安装 Android Sdk 了。因为服务器是隔离外网环境,所以我直接主机的 sdk 和 gradle 缓存拷进容器,构建时便无需访问网络了。

$ sudo docker cp $ANDROID_HOME gitlab-runner:/sdk
$ sudo docker cp ~/.gradle gitlab-runner:/home/gitlab-runner/.gradle

建议删除其他无用的 API 版本和 build tools 版本以节省空间。.gradle 可以只保留相应的 wrapper 版本和项目用到的 maven 库的缓存。

如果服务器能访问外网,建议直接安装 Android 命令行工具,然后通过 sdkmanager 安装需要的工具,比如:sdkmanager "platforms;android-26"

也可,直接在 docker 仓库上找一些现成的容器更方便,比如 jangrewe/gitlab-ci-android

CI

.gitlab-ci.yml

关于 unaligned apk: https://stackoverflow.com/questions/30366905/difference-between-app-debug-apk-and-app-debug-unaligned-apk/33886306

多分支

Cache

在每个 jobs 之间共享文件,可以跨 pipeline。在每个 job 开始的时候,恢复 cache。在 完成 job,上传 artifacts 之前上传。

下面的配置,在不同 pipeline 相同 job 之间共享 cache,$CI_JOB_NAME 指的是当前 job 的名称:

    # Define list of files that should be cached between subsequent runs
    cache:
      key: "$CI_JOB_NAME" # To enable per-stage caching
      untracked: true # Cache all Git untracked files

Job

在 job 名称前加一个 . 可以停用该 job

.hidden_job:
  script:
    - run test

Pipeline

Jacoco

Component 测试

keyboard_arrow_up