我们要在内网安装GitLab,Nexus3和Jenkins。通过Docker把所有软件安装到一台主机上,假设这台主机的内网IP为192.168.0.55。首先要确保这台机器上安装了Docker和Git。

使用Docker安装Mysql

GitHub -> sameersbn/docker-mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
docker pull sameersbn/mysql:latest

mkdir -p /usr/docker-volume/gitlab/mysql

docker run -tid --name=gitlab_mysql \
-p 3306:3306 \
-e 'DB_NAME=demo' \
-e 'DB_USER=fubai' \
-e 'DB_PASS=123456' \
-v /usr/docker-volume/gitlab/mysql:/var/lib/mysql \
sameersbn/mysql:latest

docker logs gitlab_mysql
使用Docker安装Redis

GitHub -> sameersbn/docker-redis

1
2
3
4
5
6
7
8
9
10
11
docker pull sameersbn/redis:latest

mkdir -p /usr/docker-volume/gitlab/redis

docker run -tid --name=gitlab_redis \
--restart=always \
-p 6379:6379 \
-v /usr/docker-volume/gitlab/redis:/var/lib/redis \
sameersbn/redis:latest

docker logs gitlab_redis
使用Docker安装GitLab

GitHub -> sameersbn/docker-gitlab

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
docker pull sameersbn/gitlab:8.7.6

mkdir -p /usr/docker-volume/gitlab/data /usr/docker-volume/gitlab/backup /usr/docker-volume/gitlab/log

docker run -tid --name='gitlab' \
--link gitlab_mysql:mysql \
--link gitlab_redis:redisio \
-e 'GITLAB_PORT=80' \
-e 'GITLAB_SSH_PORT=22' \
-e 'GITLAB_HOST=192.168.0.55' \
-e 'SMTP_ENABLED=true' \
-e 'SMTP_DOMAIN=www.qq.com' \
-e 'SMTP_HOST=smtp.exmail.qq.com' \
-e 'SMTP_PORT=25' \
-e 'SMTP_STARTTLS=false' \
-e 'SMTP_USER=SMTP邮箱' \
-e 'SMTP_PASS=SMTP密码' \
-e 'SMTP_AUTHENTICATION=login' \
-e 'GITLAB_BACKUP_DIR=/usr/docker-volume/gitlab/backup' \
-e 'GITLAB_BACKUP_SCHEDULE=weekly' \
-e 'GITLAB_BACKUP_EXPIRY=604800' \
-e 'GITLAB_SECRETS_DB_KEY_BASE=64位随机字符串' \
-p 80:80 \
-p 22:22 \
-v /var/run/docker.sock:/run/docker.sock \
-v $(which docker):/bin/docker \
-v /usr/docker-volume/gitlab/data:/home/git/data \
-v /usr/docker-volume/gitlab/log:/var/log/gitlab \
sameersbn/gitlab:8.7.6

docker logs gitlab

运行GitLab的Docker镜像时,将远程主机的8022端口转发到了Docker上,所以要保证远程主机的80和22端口未被占用,如果远程主机的sshd在使用22端口,将其修改成其它的端口。

假设要将远程主机的sshd端口号修改为10022,需要将/etc/ssh/sshd_configPort修改为10022,然后重启sshd: service ssh restart

远程登录可以使用ssh -p 10022 用户名@主机ip,远程拷贝可以使用: scp -P 10022 本地文件 用户名@远程主机IP:远程主机目录

64位随机字符串的生成可以使用: pwgen -Bsv1 64

使用Docker安装Nexus3

GitHub -> sonatype/docker-nexus3

1
2
3
4
5
6
7
8
9
10
11
12
13
docker pull sonatype/nexus3

mkdir -p /usr/docker-volume/nexus-data

chown -R 200 /usr/docker-volume/nexus-data

docker run -tid --name=nexus \
--privileged=true \
-p 8081:8081 \
-v /usr/docker-volume/nexus-data:/nexus-data \
sonatype/nexus3

docker logs nexus

安装Nexus3时,需要将数据卷的uid修改为Docker容器中nexus用户的uid,这个uid可以在对应的Dockfile中找到。

如果不修改,那么改数据卷的所属用户为root,Nexus3运行时,其运行用户nexus将没有权限修改数据卷中的内容,导致Nexus3无法正常运行。

使用Docker安装Jenkins

GitHub -> jenkinsci/docker

构建Docker镜像
下载相关文件
1
git clone https://github.com/jenkinsci/docker.git

下载apache-maven-3.3.9-bin.tar.gz,并移动到jenkinsci/docker文件夹内

下载tini-static(需要翻墙),并移动到jenkinsci/docker文件夹内,修改其名称为tini

在jenkinsci/docker文件夹下添加settings.xml
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
<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>/var/jenkins_home/.m2/repository</localRepository>

<pluginGroups>
</pluginGroups>

<proxies>
</proxies>

<servers>
<server>
<id>maven-releases</id>
<username>Nexus用户名</username>
<password>密码</password>
</server>
<server>
<id>maven-snapshots</id>
<username>Nexus用户名</username>
<password>密码</password>
</server>
</servers>

<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<name>mirrorOfAll</name>
<url>http://192.168.0.55:8081/repository/maven-public/</url>
</mirror>
</mirrors>

<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>

<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
修改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
FROM java:8-jdk

RUN apt-get update && apt-get install -y git curl zip && rm -rf /var/lib/apt/lists/*

ENV JENKINS_HOME /var/jenkins_home
ENV JENKINS_SLAVE_AGENT_PORT 50000

ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000

# Jenkins is run with user `jenkins`, uid = 1000
# If you bind mount a volume from the host or a data container,
# ensure you use the same uid
RUN groupadd -g ${gid} ${group} \
&& useradd -d "$JENKINS_HOME" -u ${uid} -g ${gid} -m -s /bin/bash ${user}

# Jenkins home directory is a volume, so configuration and build history
# can be persisted and survive image upgrades
VOLUME /var/jenkins_home

# `/usr/share/jenkins/ref/` contains all reference configuration we want
# to set on a fresh new installation. Use it to bundle additional plugins
# or config file with your custom jenkins Docker image.
RUN mkdir -p /usr/share/jenkins/ref/init.groovy.d

ENV TINI_SHA 066ad710107dc7ee05d3aa6e4974f01dc98f3888

# Use tini as subreaper in Docker container to adopt zombie processes
COPY tini /bin/tini
RUN chmod +x /bin/tini \
&& echo "$TINI_SHA /bin/tini" | sha1sum -c -

COPY init.groovy /usr/share/jenkins/ref/init.groovy.d/tcp-slave-agent-port.groovy

ARG JENKINS_VERSION
ENV JENKINS_VERSION ${JENKINS_VERSION:-1.651.2}
ARG JENKINS_SHA
ENV JENKINS_SHA ${JENKINS_SHA:-f61b8b604acba5076a93dcde28c0be2561d17bde}

# could use ADD but this one does not check Last-Modified header
# see https://github.com/docker/docker/issues/8331
RUN curl -fsSL http://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/${JENKINS_VERSION}/jenkins-war-${JENKINS_VERSION}.war -o /usr/share/jenkins/jenkins.war \
&& echo "$JENKINS_SHA /usr/share/jenkins/jenkins.war" | sha1sum -c -

ENV JENKINS_UC https://updates.jenkins.io
RUN chown -R ${user} "$JENKINS_HOME" /usr/share/jenkins/ref

ADD ./apache-maven-3.3.9-bin.tar.gz /usr/local/lib

ENV M2_HOME /usr/local/lib/apache-maven-3.3.9

RUN ln -s /usr/local/lib/apache-maven-3.3.9/bin/mvn /usr/bin/mvn && mkdir -p $JENKINS_HOME/.m2

COPY settings.xml $JENKINS_HOME/.m2/settings.xml

# for main web interface:
EXPOSE 8080

# will be used by attached slave agents:
EXPOSE 50000

ENV COPY_REFERENCE_FILE_LOG $JENKINS_HOME/copy_reference_file.log

USER ${user}

COPY jenkins.sh /usr/local/bin/jenkins.sh
ENTRYPOINT ["/bin/tini", "--", "/usr/local/bin/jenkins.sh"]

# from a derived Dockerfile, can use `RUN plugins.sh active.txt` to setup /usr/share/jenkins/ref/plugins from a support bundle
COPY plugins.sh /usr/local/bin/plugins.sh
构建镜像
1
docker build -t jenkins-maven .
运行Jenkins
1
2
3
4
5
6
7
8
9
mkdir -p /usr/docker-volume/jenkins

chown -R 1000 /usr/docker-volume/jenkins

docker run -tid --name=jenkins \
--privileged=true \
-p 8082:8080 \
-p 50000:50000 \
-v /usr/docker-volume/jenkins:/var/jenkins_home jenkins-maven
将GitLab上指定的项目关联到Slack指定的频道中
添加Slack的Webhook
  • 首先要为channel(Slack->team->channel)创建webhooks,Slack会给你一个webhooks的url,不同team的创建地址都不同,需要你自己找到自己team的webhooks的创建地址。

  • 以管理员帐号登陆GitLab,然后是:某项目 -> Settings -> Services -> Slack,现在进入到了GitLab上的指定项目的Slack设置页面,选中Active,将上一步的到的url输入到Webhook中,点击Save changes

Slack的webhook可以被GitLab调用。在code,wiki和issue等发生变化时,GibLab将特定的信息发送到对应的webhook上,然后Slack会将其发送到指定的频道中,如下图:

配置Jenkins
安全配置

系统管理 -> Configure Global Security,配置为下图:

保存之后,页面右上角出现注册链接,点击进入后注册一个用户,然后进行下图的配置:

先在添加 用户/组:添加刚刚注册的用户,然后作出如图所示的配置,保存后就可以了。

上述配置是关闭Jenkins的匿名用户访问,并取消用户注册功能,建立了一个用户帐号jenkins,只有该用户可以登陆Jenkins。

安装插件

在可用插件中选择Deploy to container PluginGit client pluginGit pluginGitLab Plugin后安装

系统设置
JDK 设置
Maven 设置
Git 设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. 查看容器id
docker ps

2. 进入容器
docker exec -it <容器id> /bin/sh

3. 为Git配置用户名密码
git config --global user.email "xxx@xxx.com"
git config --global user.name "xxx"

4. 生成SSH key
ssh-keygen -t rsa -C "xxx@xxx.com"

5. 将SSH key生成的公钥添加到GitLab中,这里先要在GitLab中注册一个帐号。GitLab提供了deploy key的方式来为CI服务器提供Git服务,但是我这里并没有采用。
GitLab 设置
创建Jenkins Task
构建一个maven项目

在上面构建Jenkins的Docker镜像时,我们已经为Jenkins安装并配置了Maven,所以可以不需要再为一个maven deploy操作配置nexus3私服的信息,下面开始配置:

先进入源码管理选项,选择Git,然后在Credentials处点击Add,进行如下图的设置:

然后进行如下几张图的设置:

  • 图一:

  • 图二:

  • 图三:

  • 图四:

  • 图五:

  • 图六:

总结

通过创建Jenkins任务可以看到,Jenkins会使用Git从GitLab上拉取demo-api,然后通过Maven将其打包发布到Nexus中。最后使用将打包生成的war文件发布到Tomcat中去。

这个Jenkins任务的触发条件是GitLab,在图三中可以看到有一个GitLab CI Service URL,这个url就是这个Jenkins任务的web hook,需要将其拷贝粘贴到GitLab对应项目的web hook中,即图六所示。

这里的demo-api是我创建的一个Maven项目,对外提供了几个简单的REST API接口。通过Git将其push到GitLab上之后,在GitLab上创建该项目REST API对应的WIKI说明。

假设有两个开发人员AB,A是后端开发人员,B是前端开发人员。A和B都在同一个Slack的频道中,而且,该频道的web hook在GibLab上被绑定到了A开发的后端项目上。现在,A修改了后台的Rest API,测试通过后,在GitLab上修改该API对应的WIKI说明。对WIKI的修改会向Slack频道中发送一条消息,那么,B现在就知道了A修改了API。然后A将代码提交到GitLab中,GitLab会调用Slack的web hook,将本次提交的相关信息发送到Slack的频道中。于是,B又收到了A确切提交的相关信息。与此同时,GitLab调用Jenkins的web hook,触发Jenkins任务。Jenkins使用Maven将后端项目编译打包后,部署到Tomcat中。那么B就能访问最新的API了。