logo
59
182
WeChat Login

如何实现完整CICD部署Docker镜像到腾讯云服务器?#2222

Resolved
created 2025-10-15
Edit

这个特性将解决什么问题?

从Codeup迁移过来, 功能很多, 也很有前途.

但是例如 Push、Build、推送到CNB Docker仓库以后, 如何使用插件等方式流水化在对应的腾讯云服务器拉取和更新镜像服务?

如果这一步做不到, 自家生态就真的一点也不完整...

再例如传统SSH插件方式手动敲命令, 那么这个流水线就真的很麻烦了...

设想的解决方案?如有

Administrator
7ce3c04e-e580-4f0a-9ef8-d433c6719498.png
Administrator

prompt:“请帮我生成一个.cnb.yml 文件,可以实现将 代码构建成docker 制品并推送到腾讯云镜像服务”

`stages:

阶段1:构建Docker镜像(关键阶段~)

  • name: docker build
    services:
    • docker # 启用docker服务
      docker:
      build:
      dockerfile: Dockerfile # 假设你的Dockerfile在项目根目录~
      by:
      • nginx.conf # 如果有需要的话,可以添加构建参数(参考之前的讨论~)
        script:
    • echo "✨ 开始构建Docker镜像..."
    • docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${CNB_COMMIT} . # 打标签+构建命令~

阶段2:登录腾讯云镜像仓库(推送前必须~)

  • name: docker login
    services:
    • docker
      script:
    • echo "🔑 登录腾讯云镜像仓库..."
    • docker login -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}" ${CNB_DOCKER_REGISTRY} # 用上下文里的变量自动填充凭证~

阶段3:推送镜像到仓库(核心操作~)

  • name: docker push
    services:
    • docker
      script:
    • echo "🚀 推送Docker镜像到仓库..."
    • docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${CNB_COMMIT} # 推送最新提交的镜像~

阶段4:清理旧镜像标签(可选但推荐~只保留最新~)

  • name: remove old docker tags
    type: artifact:remove-tag # 使用制品清理功能
    options:
    name: ${CNB_REPO_SLUG_LOWERCASE} # 仓库名
    tags:
    - ${CNB_COMMIT} # 保留当前提交的标签,其他旧标签会被清理~
    type: docker # 指定清理类型为docker镜像

services:

  • docker # 全局启用docker服务~
`
added labels
使用问题:用法咨询
removed labels
仅讨论
  • 如果你指的是在腾讯云服务器上,即腾讯云服务器CVM或者轻量服务器Lighthouse里面的容器运行环境(Docker Podman……)。常用的方案是在流水线中使用ssh连接到服务器,自动化拉取的过程(确实是手敲,但也只用敲一次,还能让AI帮你写)
  • 如果你说的是在腾讯容器托管平台TKE,或者其它什么容器平台,可以在流水线中使用对应的API或者CLI/SDK(如有)触发拉取或者直接推送。我有一个工具项目就是使用CI部署到Cloudflare,使用的是CF 官方的wrangler CLI工具,看看能不能从中得到什么灵感
Creator

prompt:“请帮我生成一个.cnb.yml 文件,可以实现将 代码构建成docker 制品并推送到腾讯云镜像服务”

`stages:

阶段1:构建Docker镜像(关键阶段~)

  • name: docker build
    services:
    • docker # 启用docker服务
      docker:
      build:
      dockerfile: Dockerfile # 假设你的Dockerfile在项目根目录~
      by:
      • nginx.conf # 如果有需要的话,可以添加构建参数(参考之前的讨论~)
        script:
    • echo "✨ 开始构建Docker镜像..."
    • docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${CNB_COMMIT} . # 打标签+构建命令~

阶段2:登录腾讯云镜像仓库(推送前必须~)

  • name: docker login
    services:
    • docker
      script:
    • echo "🔑 登录腾讯云镜像仓库..."
    • docker login -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}" ${CNB_DOCKER_REGISTRY} # 用上下文里的变量自动填充凭证~

阶段3:推送镜像到仓库(核心操作~)

  • name: docker push
    services:
    • docker
      script:
    • echo "🚀 推送Docker镜像到仓库..."
    • docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:${CNB_COMMIT} # 推送最新提交的镜像~

阶段4:清理旧镜像标签(可选但推荐~只保留最新~)

  • name: remove old docker tags
    type: artifact:remove-tag # 使用制品清理功能
    options:
    name: ${CNB_REPO_SLUG_LOWERCASE} # 仓库名
    tags:
    - ${CNB_COMMIT} # 保留当前提交的标签,其他旧标签会被清理~
    type: docker # 指定清理类型为docker镜像

services:

  • docker # 全局启用docker服务~
`

@Teewee(天空)

非常感谢!我想补充下,我想的是Git Push以后触发云构建,上传制品到cnb docker制品仓库,然后同步腾讯云服务器(或轻量云服务器)下载对应镜像并进行down和up -d操作进行替换。

以下两个示例结合着用可以实现:

https://cnb.cool/examples/ecosystem/react-docker
https://cnb.cool/examples/ecosystem/react-ssh-demo

晚点我们出一个示例好一些

1
Creator

以下两个示例结合着用可以实现:

https://cnb.cool/examples/ecosystem/react-docker
https://cnb.cool/examples/ecosystem/react-ssh-demo

晚点我们出一个示例好一些

@youkun(哪都通在逃临时工) 非常感谢!!毕竟是自家产品,有个CNB流水线推送到腾讯云服务器的Demo 会方便更多人参考

Creator

已经更新最佳实践和相关仓库哈

examples/showcase#144
https://cnb.cool/examples/ecosystem/react-docker

@youkun(哪都通在逃临时工) Good!! 极其高效!感谢大佬!

Resolved ISSUE
Reopen
Creator

已经更新最佳实践和相关仓库哈

examples/showcase#144
https://cnb.cool/examples/ecosystem/react-docker

@youkun(哪都通在逃临时工) Sorry 还有个问题,如何在cnb中使用dockerFile部署?部署后推送Dockerfile制品(后续一样)

Creator

例如我之前阿里云的DockerFile如下:

`FROM golang:latest as builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build
-ldflags="-w -s"
-trimpath
-o XXXX ./cmd/client

STEP 2: Run service

FROM alpine:latest

ENV TZ=Asia/Shanghai

WORKDIR /app

COPY --from=builder /app/XXXX .

RUN apk add curl tzdata ca-certificates dumb-init
RUN chmod +x ./XXXX &&
curl -L -o ./GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb

VOLUME ["/app/logs"]

EXPOSE 8877

ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["./XXXX"]`

在.cnb.yml应该如何编写呢...

Administrator

@youkun(哪都通在逃临时工) Sorry 还有个问题,如何在cnb中使用dockerFile部署?部署后推送Dockerfile制品(后续一样)

@atsauce(Artisan) 你好
首先,Dockerfile 本身不是部署描述文件,是构建描述文件,在流水线里 docker build -f Dockerfile 后得到一个容器产物,你要部署得依赖这个产物
然后,流水线的产物你需要先持久化下来到 cnb ,也就是 docker push,后续再通过其他方式触发部署机器去拉取这个产物,当然你可以参考前面说的,在流水线中使用ssh连接到服务器,自动化拉取,但是这个过程由于产物没有持久化下来,没有办法重复部署,即使相同构建要素也没法保证产物一致。

过程和 https://cnb.cool/examples/ecosystem/react-docker/-/blob/main/.cnb.yml 里是一样的,docker build 时加上 -f 指定 Dockerfile 地址即可。

2
Creator

@atsauce(Artisan) 你好
首先,Dockerfile 本身不是部署描述文件,是构建描述文件,在流水线里 docker build -f Dockerfile 后得到一个容器产物,你要部署得依赖这个产物
然后,流水线的产物你需要先持久化下来到 cnb ,也就是 docker push,后续再通过其他方式触发部署机器去拉取这个产物,当然你可以参考前面说的,在流水线中使用ssh连接到服务器,自动化拉取,但是这个过程由于产物没有持久化下来,没有办法重复部署,即使相同构建要素也没法保证产物一致。

过程和 https://cnb.cool/examples/ecosystem/react-docker/-/blob/main/.cnb.yml 里是一样的,docker build 时加上 -f 指定 Dockerfile 地址即可。

@anthonywan(Anthonywan) 学会(fei)了 谢谢。

希望能够完善Demo,更加多样化。

同时希望加入go mod 下载加速或香港等海外构建节点,build了59分钟,使用阿里云flow才3分钟....

19684714-36ae-4f5a-a4a5-a384d274b709.png
Creator

其中58分钟不知道在干啥..

a2ad6a53-7a1e-4666-8411-2453751442dd.png
Administrator

是否方便提供下仓库地址,这个可能和网络因为有关,因为我不知道你的 dockerfile 里在干啥,不太能给出准确答复

但是你可以告知下你里面下载了哪些组件,如果没有敏感信息的话,将 log 下载贴上来也可以,合理的域名我们评估下可以提供加速

是在下载这个? https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb

Creator

是否方便提供下仓库地址,这个可能和网络因为有关,因为我不知道你的 dockerfile 里在干啥,不太能给出准确答复

但是你可以告知下你里面下载了哪些组件,如果没有敏感信息的话,将 log 下载贴上来也可以,合理的域名我们评估下可以提供加速

是在下载这个? https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb

@anthonywan(Anthonywan) 可能是的... 我贴出我的cnb.yml和Dockerfile脱敏配置

`.pipeline-template: &api_web_pipeline_body
docker:
image: docker:cli
services:
- docker
imports:
- https://cnb.cool/xxx/Common/-/blob/main/xxxxxx.yml
env:
CLIENT_DOCKERFILE: cmd/client/Dockerfile
WEB_DOCKERFILE: cmd/web/Dockerfile
CLIENT_IMAGE: $CNB_DOCKER_REGISTRY/$CNB_REPO_SLUG_LOWERCASE/xxx-service-client
WEB_IMAGE: $CNB_DOCKER_REGISTRY/$CNB_REPO_SLUG_LOWERCASE/xxx-service-web
CLIENT_PORT: 8877
WEB_PORT: 8878
LOG_DIR: /data/xxx/logs
stages:
- name: Login Registry
script:
- docker login ${CNB_DOCKER_REGISTRY} -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}"

- name: Build Client Image
  script:
    - docker build -f ${CLIENT_DOCKERFILE} -t ${CLIENT_IMAGE}:latest .

- name: Push Client Image
  script:
    - docker push ${CLIENT_IMAGE}:latest

- name: Build Web Image
  script:
    - docker build -f ${WEB_DOCKERFILE} -t ${WEB_IMAGE}:latest .

- name: Push Web Image
  script:
    - docker push ${WEB_IMAGE}:latest

- name: Deploy Client Service
  image: tencentcom/ssh
  settings:
    host: $API_REMOTE_HOST
    port: $REMOTE_PORT
    username: $REMOTE_USERNAME
    key: $REMOTE_PRIVATE_KEY
    script:
      - |
        set -e
        sudo su - <<EOF
        set -e
        docker login ${CNB_DOCKER_REGISTRY} -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}"
        docker pull ${CLIENT_IMAGE}:latest
        docker stop xxx-service-client || true
        docker rm xxx-service-client || true
        mkdir -p ${LOG_DIR}
        docker run -d --name xxx-service-client \
          -v ${LOG_DIR}:/app/logs \
          -p ${CLIENT_PORT}:${CLIENT_PORT} \
          --restart=unless-stopped \
          --health-cmd="curl -f http://localhost:${CLIENT_PORT}/live || exit 1" \
          --health-interval=30s \
          --health-timeout=10s \
          --health-retries=3 \
          --health-start-period=60s \
          ${CLIENT_IMAGE}:latest
        docker ps --filter "name=xxx-service-client"
        EOF

- name: Deploy Web Service
  image: tencentcom/ssh
  settings:
    host: $API_REMOTE_HOST
    port: $REMOTE_PORT
    username: $REMOTE_USERNAME
    key: $REMOTE_PRIVATE_KEY
    script:
      - |
        set -e
        sudo su - <<EOF
        set -e
        docker login ${CNB_DOCKER_REGISTRY} -u ${CNB_TOKEN_USER_NAME} -p "${CNB_TOKEN}"
        docker pull ${WEB_IMAGE}:latest
        docker stop xxx-service-web || true
        docker rm xxx-service-web || true
        mkdir -p ${LOG_DIR}
        docker run -d --name xxx-service-web \
          -v ${LOG_DIR}:/app/logs \
          -p ${WEB_PORT}:${WEB_PORT} \
          --restart=unless-stopped \
          --health-cmd="curl -f http://localhost:${WEB_PORT}/live || exit 1" \
          --health-interval=30s \
          --health-timeout=10s \
          --health-retries=3 \
          --health-start-period=60s \
          ${WEB_IMAGE}:latest
        docker ps --filter "name=xxx-service-web"
        EOF

master:
push:
- name: api-web-build-and-deploy
<<: *api_web_pipeline_body

pull_request:
- name: api-web-build-and-deploy
<<: *api_web_pipeline_body`

DockerFile:

`# STEP 1: Build service
FROM golang:latest as builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build
-ldflags="-w -s"
-trimpath
-o xxx ./cmd/client

STEP 2: Run service

FROM alpine:latest

ENV TZ=Asia/Shanghai

WORKDIR /app

COPY --from=builder /app/xxx .

RUN apk add curl tzdata ca-certificates dumb-init
RUN chmod +x ./xxx &&
curl -L -o ./GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-City.mmdb

VOLUME ["/app/logs"]

EXPOSE 8877

ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["./xxxx"]`

go mod 不知道有没有加速...

Administrator

goproxy 有加速的,确认就是下载 GeoLite2-City.mmdb 撞墙了,正常都要MB/s起,但是你截图里就K/s的速度,但是 github.com 是有加速的,我们确认下这个问题

1
Creator

goproxy 有加速的,确认就是下载 GeoLite2-City.mmdb 撞墙了,正常都要MB/s起,但是你截图里就K/s的速度,但是 github.com 是有加速的,我们确认下这个问题

@anthonywan(Anthonywan) OK TKS

Resolved ISSUE
Assignee
None yet
Label
使用问题:用法咨询
Priority
None yet
Time period
-
Property
Add custom properties to record and label key information
Participant