知乎专栏 |
项目目录下面创建 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 部署的软件包
进入查看详情
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
创建或编辑 ~/.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$
查看软件包
查看详细信息
登陆 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/*
创建项目访问令牌,这里不再赘述,前面已经讲过。
登陆到 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
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; } }
在 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" }
构建镜像
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
推送完成后,前往“容器镜像库”可以看到镜像
查看镜像
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}" .