将 Docker 镜像推送到 GitLab Container Registry 的完整步骤
一、前提准备
-
GitLab 项目:
- 在 GitLab 上拥有一个项目,例如
your-group/your-project-name
。 - 重要: 确保项目路径(尤其是项目名称部分)全部使用小写字母。例如,如果初始是
Your-Project
,请在项目设置中将其路径修改为your-project
。 - 在项目中启用 Container Registry 功能 (通常默认启用)。可以在项目的
Settings -> Packages & Registries
中查看。
- 在 GitLab 上拥有一个项目,例如
-
GitLab Personal Access Token (PAT):
- 登录 GitLab。
- 进入用户设置 (
右上角头像 -> Edit profile -> Access Tokens
)。 - 创建一个新的 Personal Access Token。
- 关键权限 (Scopes): 授予该 PAT
read_registry
和write_registry
权限。 - 复制生成的 PAT 字符串并妥善保管,它只显示一次。
-
本地 Docker 环境:
- 安装并运行 Docker Desktop 或 Docker Engine。
-
项目代码和 Dockerfile:
- 你的应用程序代码(例如 Spring Boot 后端、Vue 前端)。
- 为每个需要构建镜像的应用准备好
Dockerfile
(例如Dockerfile.backend
,Dockerfile.frontend
)。
二、配置项目 .env
文件
在你的项目(通常在 docker/
目录下或项目根目录)创建一个 .env
文件,用于存储配置变量。核心内容如下:
# --- GitLab Container Registry 配置 ---
# 1. DOCKER_REGISTRY: GitLab Registry 的完整路径
# 格式: registry.gitlab.com/<你的组名>/<你的项目名全小写>
DOCKER_REGISTRY=registry.gitlab.com/your-group/your-project-name# 2. COMPOSE_PROJECT_NAME: 用于构成镜像名称的一部分 (可选, 但脚本中使用了)
# 例如 'xsgl', 最终镜像名会是 .../your-project-name/xsgl-backend
COMPOSE_PROJECT_NAME=myapp# 3. 镜像标签 (可选, 默认为 latest)
BACKEND_IMAGE_TAG=v1.0
FRONTEND_IMAGE_TAG=v1.0# --- GitLab 凭据 (用于脚本,如果选择硬编码或从 .env 加载) ---
# 警告: 直接在 .env 中存储 PAT 有安全风险,更好的方式是运行时输入或使用更安全的凭据管理
# 如果脚本设计为提示输入,则这两项可以省略
# GITLAB_USERNAME="你的GitLab用户名"
# GITLAB_PAT="你的GitLab_PAT字符串"# --- 其他应用相关配置 (例如数据库密码、API密钥等) ---
# MYSQL_ROOT_PASSWORD=your_strong_password
# ... 其他配置 ...
请将 registry.gitlab.com/your-group/your-project-name
替换为你的实际 GitLab Registry 路径,并确保项目名是小写的。
三、编写/修改构建和推送脚本 (build-push.sh
)
这是一个 Bash 脚本,用于自动化构建应用、构建 Docker 镜像并将其推送到 GitLab Registry。
核心代码片段 (build-push.sh
):
#!/bin/bash# ... (脚本头部,加载 .env 等,见之前脚本) ...# --- 定义镜像名称 --- #
# 使用 .env 中的 DOCKER_REGISTRY, COMPOSE_PROJECT_NAME, *_IMAGE_TAG
BACKEND_IMAGE_FULL_NAME="${DOCKER_REGISTRY}/${COMPOSE_PROJECT_NAME}-backend:${BACKEND_IMAGE_TAG:-latest}"
FRONTEND_IMAGE_FULL_NAME="${DOCKER_REGISTRY}/${COMPOSE_PROJECT_NAME}-frontend:${FRONTEND_IMAGE_TAG:-latest}"echo "将要构建并推送以下镜像:"
echo " 后端: $BACKEND_IMAGE_FULL_NAME"
echo " 前端: $FRONTEND_IMAGE_FULL_NAME"# --- 登录到 Docker Registry --- #
# 从 DOCKER_REGISTRY 变量中提取主机名 (registry.gitlab.com)
DOCKER_REGISTRY_HOST=$(echo "$DOCKER_REGISTRY" | awk -F/ '{print $1}') # 应为 registry.gitlab.comif [ -z "$DOCKER_REGISTRY_HOST" ]; thenecho "错误: 无法从 DOCKER_REGISTRY ($DOCKER_REGISTRY) 中提取主机名。"exit 1
fi# --- Docker 登录方式选择 ---
# 方式1: 运行时提示输入 (更安全)
# echo "--- GitLab Docker Registry 登录 ---"
# read -p "请输入您的 GitLab 用户名: " GITLAB_USERNAME
# read -s -p "请输入您的 GitLab Personal Access Token (具有 read_registry 和 write_registry 权限): " GITLAB_PAT
# echo ""# 方式2: 硬编码 (有安全风险,如之前讨论)
GITLAB_USERNAME="your-gitlab-username" # 替换为你的 GitLab 用户名
GITLAB_PAT="your-gitlab-pat-string" # 替换为你的 PATif [ -z "$GITLAB_USERNAME" ] || [ -z "$GITLAB_PAT" ]; thenecho "错误: GitLab 用户名或 PAT 未提供/设置。"exit 1
fiecho "正在尝试登录到 $DOCKER_REGISTRY_HOST ..."
echo "$GITLAB_PAT" | docker login "$DOCKER_REGISTRY_HOST" -u "$GITLAB_USERNAME" --password-stdin
LOGIN_EXIT_CODE=$?
echo "Docker login 命令退出状态码: $LOGIN_EXIT_CODE"if [ $LOGIN_EXIT_CODE -ne 0 ]; thenecho "错误: Docker 登录到 $DOCKER_REGISTRY_HOST 失败 (退出码: $LOGIN_EXIT_CODE)。"# ... (添加详细的错误检查提示) ...exit 1
fi
echo "Docker 登录成功。"# --- 构建应用程序 (示例: 后端 Maven, 前端 npm) --- #
# echo "\n>>> 开始构建后端项目..."
# cd "$PROJECT_ROOT"
# ./mvnw.cmd clean package -Dmaven.test.skip=true -f pom.xml # 或 ./mvnw ...
# echo "后端项目构建完成。"# echo "\n>>> 开始构建前端项目..."
# cd "$PROJECT_ROOT/ruoyi-ui" # 假设前端项目在 ruoyi-ui
# npm install # 如果需要
# npm run build:prod # 或其他构建命令
# echo "前端项目构建完成。"
# cd "$PROJECT_ROOT"# --- 构建 Docker 镜像 --- #
echo "\n>>> 开始构建后端 Docker 镜像..."
docker build -t "$BACKEND_IMAGE_FULL_NAME" -f "$DOCKER_DIR/Dockerfile.backend" "$PROJECT_ROOT"echo "\n>>> 开始构建前端 Docker 镜像..."
docker build -t "$FRONTEND_IMAGE_FULL_NAME" -f "$DOCKER_DIR/Dockerfile.frontend" "$PROJECT_ROOT" # 假设前端 Dockerfile 和上下文echo "Docker 镜像构建完成。"# --- 推送 Docker 镜像 --- #
echo "\n>>> 开始推送后端镜像 $BACKEND_IMAGE_FULL_NAME ..."
docker push "$BACKEND_IMAGE_FULL_NAME"echo "\n>>> 开始推送前端镜像 $FRONTEND_IMAGE_FULL_NAME ..."
docker push "$FRONTEND_IMAGE_FULL_NAME"echo "\n>>> 镜像推送完成!"
# ... (脚本尾部) ...
关键点解释:
DOCKER_REGISTRY
: 必须是registry.gitlab.com/...
。DOCKER_REGISTRY_HOST
: 脚本应正确提取出registry.gitlab.com
作为登录主机。- 登录方式: 使用
--password-stdin
配合 PAT,这是脚本化登录的推荐方式。避免将 PAT 直接作为docker login
的密码参数(不安全)。 - 镜像名称全小写: GitLab(和 Docker)要求仓库路径和镜像名称(除了标签)为全小写。
BACKEND_IMAGE_FULL_NAME
和FRONTEND_IMAGE_FULL_NAME
的构造必须符合此规则。 - 构建步骤: 脚本中应包含实际编译/构建你的应用程序的命令(例如
mvn package
,npm run build
),这些步骤在docker build
之前执行,以确保 Dockerfile 能复制到最新的构建产物。
四、执行脚本
- 确保
.env
文件配置正确。 - 确保
build-push.sh
脚本具有执行权限 (chmod +x build-push.sh
)。 - 在终端中运行脚本:
./build-push.sh
。 - 如果脚本设计为提示输入凭据,则按提示输入 GitLab 用户名和 PAT。
五、验证
推送成功后,你可以:
- 在 GitLab 项目的
Packages & Registries -> Container Registry
页面看到你推送的镜像。 - 在其他机器或环境中使用
docker pull ${DOCKER_REGISTRY}/${COMPOSE_PROJECT_NAME}-backend:${BACKEND_IMAGE_TAG}
来拉取镜像(需要先docker login registry.gitlab.com
)。
六、Mermaid 流程图
七、技术文档核心要点 (总结)
目标: 将本地构建的 Docker 镜像安全可靠地推送到 GitLab Container Registry。
- GitLab Registry 地址: 标准地址为
registry.gitlab.com
。镜像的完整路径遵循registry.gitlab.com/<group_name>/<project_name_lowercase>/<image_name>:<tag>
格式。 - 认证:
- 使用 GitLab Personal Access Token (PAT)。
- PAT 必须具有
read_registry
和write_registry
权限。 - 在脚本中使用
docker login registry.gitlab.com -u <gitlab_username> --password-stdin
,通过管道将 PAT 传递给--password-stdin
。
- 命名规范:
- GitLab 项目路径(尤其是在 Registry 中引用的部分)必须全小写。
- Docker 镜像名称(不含标签)也必须全小写。
- 脚本化:
- 使用
.env
文件管理配置变量(如DOCKER_REGISTRY
,IMAGE_TAGS
),将.env
文件加入.gitignore
。 - Bash 脚本 (
build-push.sh
) 自动化以下流程:- 加载配置。
- 执行
docker login
。 - (可选但推荐) 构建应用程序(例如
mvn package
,npm run build
)。 - 执行
docker build
,使用正确的全名和标签为镜像打 Tag。 - 执行
docker push
推送镜像。 - 包含错误检查和清晰的日志输出。
- 使用
- 关键命令片段:
.env
配置:DOCKER_REGISTRY=registry.gitlab.com/your-group/your-project-lowercase GITLAB_USERNAME="your_gitlab_username" # 或者脚本中提示输入 # GITLAB_PAT="your_pat" # 更推荐脚本中提示输入或从安全位置读取
docker login
(脚本中):echo "$GITLAB_PAT" | docker login "registry.gitlab.com" -u "$GITLAB_USERNAME" --password-stdin
docker build
(脚本中):IMAGE_FULL_NAME="${DOCKER_REGISTRY}/myimage:${TAG}" docker build -t "$IMAGE_FULL_NAME" -f path/to/Dockerfile .
docker push
(脚本中):docker push "$IMAGE_FULL_NAME"
- 常见问题与陷阱:
- Registry 主机名错误: 使用
gitlab.com
而不是registry.gitlab.com
进行登录/推送。 - 大小写问题: GitLab 项目路径或镜像名中包含大写字母。
- PAT 权限不足: PAT 未授予
write_registry
权限。 - PAT 过期或无效。
- 非 TTY 环境下的交互式登录尝试: 应使用
--password-stdin
。 - 网络/防火墙问题 阻止对
registry.gitlab.com
的访问。
- Registry 主机名错误: 使用
这份文档应该能帮助你或其他开发者理解并成功配置 GitLab Registry 的推送流程!