前言

这几天在公司内网环境搭建了一套 CI 环境,大体流程是,我们开发完代码提交到 gitlabjenkins 触发构建器,构建出 FatJar 包,其中依赖的 Jar 包到 Maven 私服下载。构建完成之后,最后将可执行的 Jar 包部署到远程的服务器上。 由于连不上外网,内网下所有的安装部署全都是离线完成的,整个搭建的过程中遇到了很多问题 ,所以这里写篇博客来记录一下。

离线安装 Docker 环境

安装 docker

通常我们安装 Docker 环境都是在线安装,不过好在官方也提供了二进制的安装文件,具体可以看官网介绍 。我们可以直接从下载页面选择我们) 选择合适的 Docker 版本到本地,下载完成之后,我们可以拷贝到内网上的服务器。官网上有具体的安装步骤,我们可以安装官网那样安装,不过这样安装就没法使用 systemctl 来管理我们的 Docker 服务。我们可以使用如下的脚步来安装。

  1. #!/bin/sh
  2. usage(){
  3. echo "Usage: $0 FILE_NAME_DOCKER_CE_TAR_GZ"
  4. echo " $0 docker-18.09.0.tgz"
  5. echo "Get docker-ce binary from: https://download.docker.com/linux/static/stable/x86_64/"
  6. echo "eg: wget https://download.docker.com/linux/static/stable/x86_64/docker-18.09.0.tgz"
  7. echo ""
  8. }
  9. SYSTEMDDIR=/usr/lib/systemd/system
  10. SERVICEFILE=docker.service
  11. DOCKERDIR=/usr/bin
  12. DOCKERBIN=docker
  13. SERVICENAME=docker
  14. if [ $# -ne 1 ]; then
  15. usage
  16. exit 1
  17. else
  18. FILETARGZ="$1"
  19. fi
  20. if [ ! -f ${FILETARGZ} ]; then
  21. echo "Docker binary tgz files does not exist, please check it"
  22. echo "Get docker-ce binary from: https://download.docker.com/linux/static/stable/x86_64/"
  23. echo "eg: wget https://download.docker.com/linux/static/stable/x86_64/docker-18.09.0.tgz"
  24. exit 1
  25. fi
  26. echo "##unzip : tar xvpf ${FILETARGZ}"
  27. tar xvpf ${FILETARGZ}
  28. echo
  29. echo "##binary : ${DOCKERBIN} copy to ${DOCKERDIR}"
  30. cp -p ${DOCKERBIN}/* ${DOCKERDIR} >/dev/null 2>&1
  31. which ${DOCKERBIN}
  32. echo "##systemd service: ${SERVICEFILE}"
  33. echo "##docker.service: create docker systemd file"
  34. cat >${SYSTEMDDIR}/${SERVICEFILE} <<EOF
  35. [Unit]
  36. Description=Docker Application Container Engine
  37. Documentation=http://docs.docker.com
  38. After=network.target docker.socket
  39. [Service]
  40. Type=notify
  41. EnvironmentFile=-/run/flannel/docker
  42. WorkingDirectory=/usr/local/bin
  43. ExecStart=/usr/bin/dockerd \
  44. -H unix:///var/run/docker.sock \
  45. --selinux-enabled=false \
  46. --log-opt max-size=1g
  47. ExecReload=/bin/kill -s HUP $MAINPID
  48. # Having non-zero Limit*s causes performance problems due to accounting overhead
  49. # in the kernel. We recommend using cgroups to do container-local accounting.
  50. LimitNOFILE=infinity
  51. LimitNPROC=infinity
  52. LimitCORE=infinity
  53. # Uncomment TasksMax if your systemd version supports it.
  54. # Only systemd 226 and above support this version.
  55. #TasksMax=infinity
  56. TimeoutStartSec=0
  57. # set delegate yes so that systemd does not reset the cgroups of docker containers
  58. Delegate=yes
  59. # kill only the docker process, not all processes in the cgroup
  60. KillMode=process
  61. Restart=on-failure
  62. [Install]
  63. WantedBy=multi-user.target
  64. EOF
  65. echo ""
  66. systemctl daemon-reload
  67. echo "##Service status: ${SERVICENAME}"
  68. systemctl status ${SERVICENAME}
  69. echo "##Service restart: ${SERVICENAME}"
  70. systemctl restart ${SERVICENAME}
  71. echo "##Service status: ${SERVICENAME}"
  72. systemctl status ${SERVICENAME}
  73. echo "##Service enabled: ${SERVICENAME}"
  74. systemctl enable ${SERVICENAME}
  75. echo "## docker version"
  76. docker version

可以将上面脚本内容保存为 install_docker.sh 脚本文件。移到到刚才下载的二进制文件压缩包(例如 docker-18.09.0.tgz)的同级目录下,运行下面命令即可完成安装。

  1. chmod +x install_docker.sh
  2. ./install_docker.sh docker-18.09.0.tgz

如果想要卸载,可以将下面脚本内容保存到 uninstall.sh ,赋权限执行即可。

  1. #!/bin/sh
  2. echo '停止docker服务'
  3. systemctl stop docker
  4. echo '删除docker.service...'
  5. rm -f /usr/lib/systemd/system/docker.service
  6. echo '删除docker文件...'
  7. rm -rf /usr/bin/docker*
  8. echo '重新加载配置文件'
  9. systemctl daemon-reload
  10. echo '卸载成功...'

安装 docker-compose

docker-composeGitHub上就能下载,可以点击下载链接,来下载最新的二进制文件,下载完成之后,拷贝到内网服务器。执行下面命令即可

  1. mv docker-compose-Linux-x86_64 docker-compose
  2. mv docker-compose /usr/local/bin/
  3. # 验证是否安装成功
  4. docker-compose -v

在外网环境准备镜像

docker 环境准备好之后,接下来我们需要准备 gitlabjenkinsnexus 的镜像文件。具体操作就是我们先再外网环境将这些镜像都下载到本地,然后使用 docker save 导出镜像文件,拷贝到内网环境,然后再使用 docker load 将镜像文件导入。这里使用到的版本基本都是最新的。具体的命令如下:

  1. # 下载镜像
  2. docker pull gitlab/gitlab-ce:latest
  3. docker pull jenkins/jenkins:lts
  4. docker pull sonatype/nexus3:latest
  5. # 导出镜像
  6. docker save gitlab/gitlab-ce:latest > gitlab.tar
  7. docker save jenkins/jenkins:lts > jenkins.tar
  8. docker save sonatype/nexus3:latest > nexus3.tar

如果网速不行的话,你就得等上一会儿了,因为这些镜像的大小还是比较大的 。 gitlab 大概在 1.8G 左右。所有需要的镜像下载完成中,同样的拷贝到内网服务器。接下来使用如下命令将所有镜像都导入到本地

  1. # 导入镜像
  2. docker load < gitlab.tar
  3. docker load < jenkins.tar
  4. docker load < nexus3.tar

导入成功后,我们使用 docker images 就能查看我们本地的镜像了。

  1. [root@CentOS7 ~]# docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. gitlab/gitlab-ce latest 2b9ac1a40dd1 7 days ago 1.81GB
  4. sonatype/nexus3 latest e56a3b1f769b 9 days ago 630MB
  5. jenkins/jenkins lts 5d1103b93f92 2 weeks ago 656MB

使用docker-compose启动镜像

我们可以一个一个单独的启动这三个应用,不过为了方便,我们可以使用 docker-compose 工具,一次将所有容器都启动起来。选择合适的目录,例如 root/ci 下,新建如下的 docker-compose.yaml 文件

  1. version: "3.6"
  2. services:
  3. gitlab:
  4. image: gitlab/gitlab-ce:latest
  5. container_name: gitlab
  6. ports:
  7. - 443:443
  8. - 80:80
  9. - 22:22
  10. volumes:
  11. - /root/ci/gitlab/config:/etc/gitlab # 映射配置文件到本地
  12. - /root/ci/gitlab/logs:/var/log/gitlab # 映射日志文件到本地
  13. - /root/ci/gitlab/data:/var/opt/gitlab # 映射数据文件到本地
  14. jenkins:
  15. image: jenkins/jenkins:lts
  16. user: root
  17. container_name: jenkins
  18. ports:
  19. - 8002:8080
  20. volumes:
  21. - /var/run/docker.sock:/var/run/docker.sock
  22. - /root/ci/jenkins:/var/jenkins_home # 映射jenkins数据到本地
  23. - /usr/bin/docker:/usr/bin/docker
  24. nexus:
  25. image: sonatype/nexus3:latest
  26. container_name: nexus
  27. user: root
  28. ports:
  29. - 8081:8081
  30. volumes:
  31. - /root/ci/nexus-data:/nexus-data # 映射nexus数据到本地

具体上面 yaml 文件里的一些参数配置,需要根据实际情况来定,例如端口的映射和数据卷的映射等。配置文件编写完成之后。我们可以直接在文件所在目录下执行 docker-compse up -d 来启动这三个容器。执行完成之后,我们可以使用 docker ps 来查看具体容器是否运行。我们也可以查看详情的应用启动日志,例如使用 docker logs -f gitlab 来查看 gitlab 启动日志。

配置Gitlab

gitlib 启动完成之后,我们还需要做一些配置,不然会有一些问题,最常见的就是新建项目之后,显示的 git 下载链接中带着容器内的主机名称。实际应该是 IP 地址或者域名。我们可以通过如下命令来修改

  1. # 首先进入到容器内
  2. docker exec -it gitlab bash
  3. # 修改 /etc/gitlab/gitlab.rb 文件
  4. vi /etc/gitlab/gitlab.rb
  5. # 找到如下内容并作出如下的修改
  6. external_url 'http://10.211.55.3' # 默认的站点Url配置项
  7. # 修改完成之后,wq 保存,然后重新配置gitlab
  8. gitlab-ctl reconfigure

reconfigure 执行完成之后,退出容器,然后执行 docker restart gitlab 重启一下。重启完成之后,我们在浏览器输入http://10.211.55.3 就能直接访问到 gitlab 了。首先我们要做的就是重置 root 账户的密码,重置完成之后,我们就可以使用 root 账户登录了。

配置 Jenkins

jenkins 容器启动之后,在容器日志中会有第一次登录需要的管理员密码,我们使用 docker logs -f jenkins 就可以看到。用初始化密码登录之后,出现的界面是插件的安装,由于我们连不上外网,所以这里可以跳过。接下来设置一个管理员用户密码,我们就进入主页了。但是插件怎么办呢,这里有两种解决办法。

  1. 先在外网环境按照上面 docker-compose 文件内容启动一个 jenkins 容器,启动完成之安装我们需要的插件,我们也可以直接安装新手入门的推荐插件。安装完成之后,我们在 系统管理 > 插件管理 > 可选插件 中搜索并安装其他我们需要的插件,例如 dockergitlabSSHPublish Over SSH 等。由于我们将容器内 jenkins_home 目录映射到了本地,所以我们直接可以从本地的目录 root/ci/jenkins/ 中看到 plugins 插件目录。我们可以直接将此目录打包拷贝到内网服务器的同名目录。然后重启容器即可。
  2. 第二种方法就是下载插件的离线安装包,下载地址在 http://updates.jenkins-ci.org/download/plugins/ ,我们可以从该页面下载我们需要的插件,格式是 hpi 。下载好之后我们拷贝到内网服务器,进入 jenkins 的插件安装目录。手动上传插件安装。

插件安装完成之后,我们还需要对 Jenkins 做一些配置。具体就是 JDKMaven 的配置,具体配置位置在 系统管理-全局工具管理 页面下。容器内自带 JDK ,位置在 usr/local/openjdk-8 ,我们可以直接填这个路径。但是容器内不带 maven ,解决方法可以是外挂一个 maven 到容器内,我们可以在 docker-composejenkins 的配置里添加一项数据卷映射,例如

  1. jenkins:
  2. image: jenkins/jenkins:lts
  3. user: root
  4. container_name: jenkins
  5. ports:
  6. - 8002:8080
  7. volumes:
  8. - /var/run/docker.sock:/var/run/docker.sock
  9. - /root/ci/jenkins:/var/jenkins_home # 映射jenkins数据到本地
  10. - /root/ci/maven:/usr/local/maven # 将本地 maven 映射到容器内
  11. - /usr/bin/docker:/usr/bin/docker

添加完成之后,我们就可以填写 maven 的地址为 /usr/local/maven 。另外 maven 的配置文件(settings)我们还需要改成 /usr/local/maven/conf/settings ,这个配置文件具体的配置在配置完 maven 私服后再设置。 另外还有一个 Publish Over SSH 配置我们在任务测试的过程中设置。

配置 Maven 私服

nexus 容器启动完成之后,我们通过映射出来的端口就可以访问到了。默认的 admin 账户密码在 /nexus-data/admin.password 文件中,我们可以进入容器内部查看。登录成功之后,我们就可以管理我们的 Repositories 了,这里我就用的默认的库。不过如何将 Jar 上传到私服里呢,如果在外网环境,我们可以通过代理到其他的公共仓库,但是在内网环境不行。不过我们也可以以脚本的方式将本地 .m2/repository 目录下的所有包导入到私服中。具体脚本内容为

  1. #!/bin/bash
  2. # copy and run this script to the root of the repository directory containing files
  3. # this script attempts to exclude uploading itself explicitly so the script name is important
  4. # Get command line params
  5. while getopts ":r:u:p:" opt; do
  6. case $opt in
  7. r) REPO_URL="$OPTARG"
  8. ;;
  9. u) USERNAME="$OPTARG"
  10. ;;
  11. p) PASSWORD="$OPTARG"
  12. ;;
  13. esac
  14. done
  15. find . -type f -not -path './mavenimport\.sh*' -not -path '*/\.*' -not -path '*/\^archetype\-catalog\.xml*' -not -path '*/\^maven\-metadata\-local*\.xml' -not -path '*/\^maven\-metadata\-deployment*\.xml' | sed "s|^\./||" | xargs -I '{}' curl -u "$USERNAME:$PASSWORD" -X PUT -v -T {} ${REPO_URL}/{} ;

我们可以先将本地的 repository 文件压缩拷贝到内网下。然后在 repository 目录下将上面脚本内容保存到 mavenimport.sh 中,按照下面命令方式执行脚本即可

  1. chmod +x mavenimport.sh
  2. # -u 用户名 -p 密码 -r 要上传的仓库,这里就是默认的
  3. ./mavenimport.sh -u admin -p admin123 -r http://ip:8081/repository/maven-releases/

执行完成之后,我们在 nexus 上就能看到我们上传的本地包了。
最后,最关键的就是配置 settings 文件,下面是一份参考的配置文件,其中 server 的用户名密码, repository 中的 ip 需要配置成自己的。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  5. <servers>
  6. <server>
  7. <id>maven-releases</id>
  8. <username>admin</username>
  9. <password>admin</password>
  10. </server>
  11. <server>
  12. <id>maven-snapshots</id>
  13. <username>admin</username>
  14. <password>admin</password>
  15. </server>
  16. </servers>
  17. <mirrors>
  18. <mirror>
  19. <id>nexus</id>
  20. <mirrorOf>*</mirrorOf>
  21. <name>nexus</name>
  22. <url>http://ip:8081/repository/maven-public/</url>
  23. </mirror>
  24. </mirrors>
  25. <profiles>
  26. <profile>
  27. <id>dev</id>
  28. <repositories>
  29. <repository>
  30. <id>nexus</id>
  31. <url>http://ip:8081/repository/maven-public/</url>
  32. <releases>
  33. <enabled>true</enabled>
  34. </releases>
  35. <snapshots>
  36. <enabled>true</enabled>
  37. </snapshots>
  38. </repository>
  39. </repositories>
  40. </profile>
  41. </profiles>
  42. </settings>

我们可以按照这份配置的内容修改前面映射到 jenkins 里的 maven 配置。

任务测试

环境准备好之后,我们就可以新建一个任务来测试了。不过我们首先需要上传一个可运行的项目到 gitlab 中。项目准备好之后,我们可以在 jenkins 中新建一个自由风格的或者 maven 项目。具体的操作图太多,我就不截图了,可以看参考目录下的链接文章。

参考