构建并推送容器镜像到容器注册表
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
在构建和推送容器镜像之前,您必须先对容器注册表进行 认证。
使用 Docker 命令
您可以使用 Docker 命令来构建和推送容器镜像到您的容器注册表:
-
认证到容器注册表。
-
运行 Docker 命令来构建或推送。例如:
-
构建:
docker build -t registry.example.com/group/project/image . -
推送:
docker push registry.example.com/group/project/image
-
使用 GitLab CI/CD
使用 GitLab CI/CD 来构建、推送、测试和部署来自容器注册表的容器镜像。
配置您的 .gitlab-ci.yml 文件
您可以配置您的 .gitlab-ci.yml 文件来构建和推送容器镜像到容器注册表。
-
如果多个作业需要认证,将认证命令放在
before_script中。 -
在构建前,使用
docker build --pull来获取基础镜像的更改。这会稍微耗时,但能确保您的镜像是最新的。 -
在每次
docker run之前,执行显式的docker pull来获取刚刚构建的镜像。如果您使用多个运行器并在本地缓存镜像,这一步尤其重要。如果您在镜像标签中使用 Git SHA,每个作业都是唯一的,您永远不会遇到过时的镜像。但是,如果在依赖项更改后重新构建某个提交,仍然可能存在过时的镜像。
-
不要直接构建到
latest标签,因为可能有多个作业同时进行。
使用 Docker-in-Docker 容器镜像
您可以将自己的 Docker-in-Docker (DinD) 容器镜像与容器注册表或依赖代理一起使用。
使用 DinD 从您的 CI/CD 管道构建、测试和部署容器化应用程序。
先决条件:
- 设置 Docker-in-Docker。
当您想使用存储在 GitLab 容器注册表中的镜像时,使用此方法。
在您的 .gitlab-ci.yml 文件中:
- 更新
image和services以指向您的注册表。 - 添加服务 别名。
您的 .gitlab-ci.yml 应该类似于这样:
build:
image: $CI_REGISTRY/group/project/docker:24.0.5
services:
- name: $CI_REGISTRY/group/project/docker:24.0.5-dind
alias: docker
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests使用此方法来缓存来自 Docker Hub 等外部注册表的镜像,以实现更快的构建速度并避免速率限制。
在您的 .gitlab-ci.yml 文件中:
- 更新
image和services以使用依赖代理前缀。 - 添加服务 别名。
您的 .gitlab-ci.yml 应该类似于这样:
build:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:24.0.5
services:
- name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:24.0.5-dind
alias: docker
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests如果您忘记设置服务别名,容器镜像将找不到 dind 服务,并显示如下错误:
error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host使用 GitLab CI/CD 的容器注册表示例
如果您在运行器上使用 DinD,您的 .gitlab-ci.yml 文件应该类似于这样:
build:
image: docker:24.0.5
stage: build
services:
- docker:24.0.5-dind
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
- docker build -t $CI_REGISTRY/group/project/image:latest .
- docker push $CI_REGISTRY/group/project/image:latest您可以在您的 .gitlab-ci.yml 文件中使用 CI/CD 变量。例如:
build:
image: docker:24.0.5
stage: build
services:
- docker:24.0.5-dind
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG在上面的示例中:
$CI_REGISTRY_IMAGE解析为与此项目关联的注册表地址。$IMAGE_TAG是一个自定义变量,它将注册表地址与$CI_COMMIT_REF_SLUG(镜像标签)组合在一起。$CI_COMMIT_REF_NAME预定义变量解析为分支或标签名称,可能包含正斜杠。镜像标签不能包含正斜杠,请使用$CI_COMMIT_REF_SLUG。
下面的示例将 CI/CD 任务分为四个流水线阶段,包括两个并行运行测试。
build 存储在容器注册表中,并由后续阶段在需要时下载容器镜像。当您向 main 分支推送更改时,流水线会将镜像标记为 latest,并使用应用程序特定的部署脚本进行部署:
default:
image: docker:24.0.5
services:
- docker:24.0.5-dind
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
stages:
- build
- test
- release
- deploy
variables:
# 使用 TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
build:
stage: build
script:
- docker build --pull -t $CONTAINER_TEST_IMAGE .
- docker push $CONTAINER_TEST_IMAGE
test1:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
test2:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
release-image:
stage: release
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
- docker push $CONTAINER_RELEASE_IMAGE
rules:
- if: $CI_COMMIT_BRANCH == "main"
deploy:
stage: deploy
script:
- ./deploy.sh
rules:
- if: $CI_COMMIT_BRANCH == "main"
environment: production上面的示例明确调用了 docker pull。如果您更喜欢使用 image: 隐式拉取容器镜像,并使用 Docker 或 Kubernetes 执行器,请确保将 pull_policy 设置为 always。