Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

11.7. 软件包与镜像库

11.7.1. Maven 仓库

项目目录下面创建 ci_settings.xml 文件

		
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
  <servers>
    <server>
      <id>gitlab-maven</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>Job-Token</name>
            <value>${env.CI_JOB_TOKEN}</value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
  </servers>
</settings>		
		
		

修改 pom.xml 文件添加下面内容

		
<repositories>
  <repository>
    <id>gitlab-maven</id>
    <url>${env.CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
  </repository>
</repositories>
<distributionManagement>
  <repository>
    <id>gitlab-maven</id>
    <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
  </repository>
  <snapshotRepository>
    <id>gitlab-maven</id>
    <url>${CI_API_V4_URL}/projects/${env.CI_PROJECT_ID}/packages/maven</url>
  </snapshotRepository>
</distributionManagement>		
		
		

修改 .gitlab-ci.yml 添加 Maven 部署命令

Docker 执行器

		
deploy:
  image: maven:3.6-jdk-11
  script:
    - 'mvn deploy -s ci_settings.xml'
  only:
    - main		
		
		

Shell 执行器

		
deploy:
  script:
    - 'mvn deploy -s ci_settings.xml'
  only:
    - main		
		
		

Maven 部署的软件包

进入查看详情

11.7.1.1. 将已存在的 JAR 文件部署到 Maven 仓库

			
package:
  stage: deploy
  variables:
    GIT_STRATEGY: none  
  script:
    - mvn deploy:deploy-file -DrepositoryId=gitlab-maven -Durl=http://registry.netkiller.cn/api/v4/projects/14/packages/maven -Dpackaging=jar -Dfile=lib/cfca.jar -DgroupId=cn.netkiller -DartifactId=cfca -Dversion=1.0.0 -Dmaven.test.skip=true -s .ci_settings.xml
    - mvn deploy:deploy-file -DrepositoryId=gitlab-maven -Durl=http://registry.netkiller.cn/api/v4/projects/14/packages/maven -Dpackaging=jar -Dfile=lib/ra-toolkit-3.6.28.2.jar -DgroupId=cn.netkiller -DartifactId=ra-toolkit -Dversion=3.6.28.2 -Dmaven.test.skip=true -s .ci_settings.xml    
    - mvn deploy -s .ci_settings.xml -Dmaven.test.skip=true
  when: manual
  allow_failure: true
  only:
    - testing			
			
			

11.7.2. Python Pypi 仓库

11.7.2.1. 个人访问令牌

创建访问令牌

[提示]提示
需要勾选 ☑️ api, read_api, read_registry, write_registry 四个授权️

将令牌复制出来保存好

11.7.2.2. 手工上传包

创建或编辑 ~/.pypirc 文件

		
[distutils]
index-servers =
    gitlab

[gitlab]
repository = https://gitlab.example.com/api/v4/projects/<project_id>/packages/pypi
username = <your_personal_access_token_name>
password = <your_personal_access_token>		
		
			

用户和密码,可以使用个人访问令牌、部署令牌和 Gitlab 用户密码

		
<project_id> 替换成你的项目URL 或者 项目 ID

例如我的项目地址是:http://registry.netkiller.cn/netkiller.cn/python.netkiller.cn/-/packages

repository = https://gitlab.example.com/api/v4/projects/netkiller.cn%2Fpython.netkiller.cn/packages/pypi	

将 “/” 替换成 “%2F”
		
			

查看项目 ID

下面是我配置,仅供参考

		
Neo-iMac:devops neo$ cat ~/.pypirc 
[distutils]
index-servers =
    gitlab

[gitlab]
repository = http://registry.netkiller.cn/api/v4/projects/30/packages/pypi
username=pypi
password=QFatUEzEybBR6gxxF5K2		
		
			

上传命令

		
Neo-iMac:devops neo$ python3 setup.py sdist bdist_wheel
Neo-iMac:devops neo$ twine upload --repository gitlab dist/*
		
			

上传演示

		
Neo-iMac:devops neo$ twine upload --repository gitlab dist/netkiller-devops-0.3.*
Uploading distributions to http://registry.netkiller.cn/api/v4/projects/30/packages/pypi
Uploading netkiller-devops-0.3.0.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.3k/37.3k [00:00<00:00, 426kB/s]
Uploading netkiller-devops-0.3.1.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.3k/37.3k [00:00<00:00, 462kB/s]
Uploading netkiller-devops-0.3.2.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.3k/37.3k [00:00<00:00, 436kB/s]
Uploading netkiller-devops-0.3.3.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.5k/37.5k [00:00<00:00, 486kB/s]
Uploading netkiller-devops-0.3.4.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.4k/37.4k [00:00<00:00, 475kB/s]
Uploading netkiller-devops-0.3.5.tar.gz
100%|███████████████████████████████████████████████████████████████████| 37.5k/37.5k [00:00<00:00, 490kB/s]
Neo-iMac:devops neo$ 		
		
			

查看软件包

查看详细信息

11.7.2.3. 在持续集成中配置

登陆 gitlab-runner 所在的服务器,如果只有 python 项目,建议使用 root 账号安装 twine 包

			
[root@localhost ~]# pip3 install twine
			
			

如果 gitlab-runner 是公共服务器,上面还会持续部署其他项目,为了项目更好隔离,可以使用 --user 参数,本地化安装

切换到 gitlab-runner,因为编译和打包,上传包都需要工作在 gitlab-runner 账号下面

			
[root@localhost ~]# su - gitlab-runner
			
			

安装 twine wheel 包

			
[gitlab-runner@localhost ~]$ pip3 install --user twine wheel
			
			

twine 将会被安装到 ~/.local/bin/twine 目录

			
[gitlab-runner@localhost ~]$ ls ~/.local/bin/twine 
/home/gitlab-runner/.local/bin/twine			
			
			

当然也可以将 twine wheel 放在 .gitlab-ci.yml 文件中,只是每次都安装一次,会影响构建性能。

			
cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - dist/
stages: 
  - build
  - test
  - deploy

build-job:
  stage: build
  tags:
    - shell
  before_script:
    - pip3 install --user netkiller-devops
    - pip3 install --user wheel twine
  script:
    - python3 setup.py sdist bdist_wheel
  # after_script:

deploy-job:
  stage: deploy
  tags:
    - shell
  before_script:
    - |
      cat > ~/.pypirc <<EOF
      [distutils]
      index-servers =
          gitlab

      [gitlab]
      repository = http://registry.netkiller.cn/api/v4/projects/30/packages/pypi
      username=pypi
      password=TUyGJW89wkdfjdh7QWAe
      EOF
    - cat  ~/.pypirc
  script:
    - ~/.local/bin/twine upload --repository gitlab dist/*			
			
			

11.7.3. Node JS

创建项目访问令牌,这里不再赘述,前面已经讲过。

登陆到 gitlab-runner 服务器,安装 Node JS 环境

		
[root@localhost ~]# dnf install -y nodejs
[root@localhost ~]# npm install -g --registry=https://registry.npm.taobao.org cnpm
[root@localhost ~]# npm install -g --registry=https://registry.npm.taobao.org yarn2
		
		

打开 Node JS 项目,编辑 package.json 文件,修改项目名称 加入 scope 例如 "name": "demo" 改为 "name": "@netkiller/demo",设置一个版本号 "version": "0.0.1",然后将 "private": true 改为 "private": false

		
{
  "name": "@netkiller/demo",
  "version": "0.0.1",
  "private": false,
  "scripts": {
    "start": "node ./bin/www",
    "test": "mocha"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "morgan": "~1.9.0",
    "pug": "2.0.0-beta11"
  },
  "devDependencies": {
    "mocha": "^5.1.1",
    "supertest": "^3.0.0"
  }
}
		
		

配置 .gitlab-ci.yml 文件

		
cache:
  paths:
    - node_modules
    - dist

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  tags:
    - shell
  script:
    - cnpm install

deploy-job:
  stage: deploy
  tags:
    - shell  
  script:
    - |
      echo -e "
      @netkiller:registry=http://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
      //${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
      " > .npmrc
    - cnpm publish		
		
		

11.7.4. Docker registry

Gitlab 默认不打开 docker registry 的功能,需要修改配置打开。

修改配置 /etc/gitlab/gitlab.rb 文件,将 registry_external_url 的值修改为 http://registry.netkiller.cn

[提示]提示
注意不能使用IP地址,如果使用IP地址必须配合端口号,且端口不能跟 Gitlab 冲突。
		
[root@gitlab ~]# grep 'registry_external_url' /etc/gitlab/gitlab.rb
# registry_external_url 'https://registry.example.com'
registry_external_url 'http://registry.netkiller.cn'		
		
		

让配置生效

		
[root@gitlab ~]# gitlab-ctl reconfigure
		
		

检查配置文件

		
[root@gitlab ~]# cat /var/opt/gitlab/nginx/conf/gitlab-registry.conf 
# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.

## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
##
###################################
##         configuration         ##
###################################


server {
  listen *:80;
  server_name registry.netkiller.cn;
  server_tokens off; ## Don't show the nginx version number, a security best practice

  client_max_body_size 0;
  chunked_transfer_encoding on;


  ## Real IP Module Config
  ## http://nginx.org/en/docs/http/ngx_http_realip_module.html

  ## HSTS Config
  ## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
  add_header Strict-Transport-Security "max-age=63072000";

  access_log  /var/log/gitlab/nginx/gitlab_registry_access.log gitlab_access;
  error_log   /var/log/gitlab/nginx/gitlab_registry_error.log error;

  location / {

    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto http;

    proxy_read_timeout                  900;
    proxy_cache off;
    proxy_buffering off;
    proxy_request_buffering off;
    proxy_http_version 1.1;

    proxy_pass          http://localhost:5000;
  }

  
}		
		
		

11.7.4.1. 配置 Docker registry

在 Gitlab Runner 运行的机器上配置 Docker registry

配置 Docker 的 daemon.json 配置文件

		
{
  "experimental": false,
  "features": {
    "buildkit": true
  },
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "insecure-registries": [
    "registry.netkiller.cn"
  ]
}		
		
			

重启 Docker 让 daemon.json

		
[root@gitlab ~]# systemctl reload docker		
		
			

我使用的 Docker Desktop for Mac,在 GUI 中配置 daemon.json 然后重启 Docker Desktop

配置 /etc/hosts 文件

		
Neo-iMac:nginx neo$ grep 'registry' /etc/hosts
192.168.30.5	registry.netkiller.cn		
		
			

Docker 登陆到 registry.netkiller.cn,登陆可以使用 gitlab 用户和密码,可以使用“个人访问令牌”和“部署令牌”,创建令牌需要给予 read_registry 和 write_registry 权限。

		
Neo-iMac:nginx neo$ docker login registry.netkiller.cn -u neo 
Password: 
Login Succeeded	
		
			

登陆成功会显示 Login Succeeded 并且会在 ~/.docker/config.json 产生配置项

		
Neo-iMac:nginx neo$ cat ~/.docker/config.json
{
	"auths": {
		"https://index.docker.io/v1/": {},
		"registry.netkiller.cn": {}
	},
	"credsStore": "desktop"
}
		
			

11.7.4.2. 手动构建镜像并上传至容器镜像库

构建镜像

		
Neo-iMac:nginx neo$ docker build -t registry.netkiller.cn/netkiller.cn/java .
[+] Building 4.5s (9/9) FINISHED                                                                                                                                                                                                                                          
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                 0.3s
 => => transferring dockerfile: 37B                                                                                                                                                                                                                                  0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                                                    0.4s
 => => transferring context: 2B                                                                                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                                                                                                                                                                                      3.1s
 => [auth] library/nginx:pull token for registry-1.docker.io                                                                                                                                                                                                         0.0s
 => [1/4] FROM docker.io/library/nginx:latest@sha256:dfef797ddddfc01645503cef9036369f03ae920cac82d344d58b637ee861fda1                                                                                                                                                0.0s
 => CACHED [2/4] RUN apt update -y && apt install -y procps                                                                                                                                                                                                          0.0s
 => CACHED [3/4] RUN apt install -y iproute2 net-tools                                                                                                                                                                                                               0.0s
 => CACHED [4/4] WORKDIR /opt                                                                                                                                                                                                                                        0.0s
 => exporting to image                                                                                                                                                                                                                                               0.4s
 => => exporting layers                                                                                                                                                                                                                                              0.0s
 => => writing image sha256:549089448b9450a2515fd4653f35c4bb828079624edcbdbc2f0607ba3656598b                                                                                                                                                                         0.0s
 => => naming to registry.netkiller.cn/netkiller.cn/java		
		
			

推送镜像

		
Neo-iMac:nginx neo$ docker push registry.netkiller.cn/netkiller.cn/java
Using default tag: latest
The push refers to repository [registry.netkiller.cn/netkiller.cn/java]
5f70bf18a086: Pushed 
2d4c9573c0b6: Pushed 
a8935bae4a3d: Pushed 
280fbd619253: Pushed 
921ee7f55927: Pushed 
fc199aaed79a: Pushed 
38aec0f8e5ed: Pushed 
ea56d6ebf7e5: Pushed 
e8b689711f21: Pushed 
latest: digest: sha256:fbb365b3dbb302bc29ef2253fbf6b9acced54fa5337fd1cb804a52713f46a0a5 size: 2199	
		
			

推送完成后,前往“容器镜像库”可以看到镜像

查看镜像

11.7.4.3. CI/CD 流水线配置

Maven 项目

pom.xml 中添加

			
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <docker.registry>registry.netkiller.cn</docker.registry>
        <docker.registry.name>netkiller.cn</docker.registry.name>
        <docker.image>api.netkiller.cn</docker.image>
        <docker.baseImage>openjdk:8-alpine</docker.baseImage>
    </properties>
			
			

plugins 插件添加

			
 			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>1.2.2</version>
				<configuration>
					<!-- <imageName>${docker.registry}/${docker.registry.name}/${project.artifactId}</imageName> -->
                    <imageName>${docker.registry}/${docker.registry.name}/${docker.image}</imageName>
					<baseImage>${docker.baseImage}</baseImage>
					<maintainer>netkiller@msn.com</maintainer>
					<volumes>/tmp</volumes>
					<workdir>/srv</workdir>
					<env>
						<JAVA_OPTS>-server -Xms512m -Xmx4096m -Djava.security.egd=file:/dev/./urandom</JAVA_OPTS>
					</env>
					<exposes>8080</exposes>
					<entryPoint>["sh", "-c", "java ${JAVA_OPTS} -jar /srv/${project.build.finalName}.jar"]</entryPoint>
					<resources>
						<resource>
							<targetPath>/srv</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
					</resources>
					<registryUrl>http://${docker.registry}/v2/</registryUrl>
					<imageTags>
						<imageTag>${project.version}</imageTag>
						<imageTag>latest</imageTag>
					</imageTags>
				</configuration>
			</plugin>
			
			

.gitlab-ci.yml

			
docker:
  stage: deploy
  before_script:
    - echo "glpat-amwpx6FWS1_mHTNUV7RU" | docker login -u "docker" --password-stdin registry.netkiller.cn
  script:
    - mvn docker:build && mvn docker:push
  after_script:
    - wechat -t 1 api.netkiller.cn Docker 镜像制作完成 http://192.168.30.5/netkiller.cn/api.netkiller.cn/container_registry
  when: manual
  allow_failure: true
  only:
    - testing			
			
			

下面在给一个 node js 项目的例子

准备 Dockerfile 文件

			
FROM nginx:alpine
LABEL author="neo"
VOLUME /etc/nginx
COPY dist/ /usr/share/nginx/html/
EXPOSE 80
WORKDIR /usr/share/nginx/html/			
			
			

.gitlab-ci.yml

			
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - dist/
    - .sonar/ 

stages:
  - build
  - test
  - deploy
  - release

deploy feature:
  stage: build
  # variables:
  environment:
    name: feature
    url: https://www.netkiller.cn
  only: 
    - /^feature\/.*/
    - feature
  tags:
    - cloud
  before_script:
    - cnpm install
    - rm -rf dist/*
    - cnpm run build:stage
  after_script:
    - wechat -t 1 www.netkiller.cn $CI_COMMIT_AUTHOR 在 $CI_COMMIT_BRANCH 环境部署完成
    - voice feature 环境部署完成
  script:
    - sed -i "s/{{description}}/$(date +"%Y-%m-%d %H:%M:%S")/" dist/index.html
    # - rsync -auv --delete dist/* /opt/netkiller.cn/car.netkiller.cn/
    - rm -rf /opt/netkiller.cn/car.netkiller.cn/*
    - \cp -af dist/* /opt/netkiller.cn/car.netkiller.cn/

feature docker:
  stage: deploy
  # variables:
  environment:
    name: feature
    url: https://www.netkiller.cn
  only: 
    - /^feature\/.*/
    - feature
  tags:
    - cloud
  before_script:
    - echo "glpat-amwpx6FWS1_mHTNUV7RU" | docker login -u "docker" --password-stdin registry.netkiller.cn
  after_script:
    - docker push registry.netkiller.cn/netkiller.cn/www.netkiller.cn -a
    - wechat -t 1 www.netkiller.cn $CI_COMMIT_AUTHOR 在 $CI_COMMIT_BRANCH Docker 镜像构建完成
    - voice feature 环境部署完成
  script:
    - docker build -t "registry.netkiller.cn/netkiller.cn/www.netkiller.cn:$(date +%Y-%m-%d.%H%M)" .

release-job:
  stage: release
  tags:
    - shell
  only:
    - master
  script:
    - |
      echo -e "
      @sfzito:registry=http://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
      //${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
      " > .npmrc
    - cnpm publish
  when: manual    

			
			

使用 ${CI_COMMIT_SHORT_SHA} 版本号作为镜像版本

			
feature docker:
  stage: deploy
  # variables:
  environment:
    name: feature
    url: https://admin.netkiller.cn
  only: 
    - /^feature\/.*/
    - feature
  tags:
    - cloud
  before_script:
    - echo "glpat-amwpx6FWS1_mHTNUV7RU" | docker login -u "docker" --password-stdin registry.netkiller.cn
  after_script:
    - docker push "registry.netkiller.cn/netkiller.cn/admin.netkiller.cn:${CI_COMMIT_SHORT_SHA}"
    - wechat -t 1 admin.netkiller.cn $CI_COMMIT_AUTHOR 在 $CI_COMMIT_BRANCH Docker 镜像构建完成
    - voice feature 环境部署完成
  script:
    - docker build -t "registry.netkiller.cn/netkiller.cn/admin.netkiller.cn:${CI_COMMIT_SHORT_SHA}" .