用于在 AWS EC2 中构建和部署 docker 映像的 CI/CD 脚本
Posted
技术标签:
【中文标题】用于在 AWS EC2 中构建和部署 docker 映像的 CI/CD 脚本【英文标题】:CI/CD script for build & deploy docker image in aws EC2 【发布时间】:2021-12-08 11:06:45 【问题描述】:我可以使用此 CI/CD 配置构建、推送(到 gitlab 注册表)和部署映像(到 aws EC2)吗?
stages:
- build
- deploy
build:
# Use the official docker image.
image: docker:latest
stage: build
services:
- docker:dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
# Default branch leaves tag empty (= latest tag)
# All other branches are tagged with the escaped branch name (commit ref slug)
script:
- |
if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
tag=""
echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
else
tag=":$CI_COMMIT_REF_SLUG"
echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
fi
- docker build --pull -t "$CI_REGISTRY_IMAGE$tag" .
- docker push "$CI_REGISTRY_IMAGE$tag"
# Run this job in a branch where a Dockerfile exists
deploy:
stage: deploy
before_script:
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
script:
- ssh -o StrictHostKeyChecking=no ubuntu@18.0.0.82 "sudo docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY; sudo docker pull $CI_REGISTRY_IMAGE$tag; cd /home/crud_app; sudo docker-compose up -d"
after_script:
- sudo docker logout
rules:
- if: $CI_COMMIT_BRANCH
exists:
- Dockerfile
脚本构建成功后,部署失败。
(构建成功)
(部署失败)
必须构建配置并部署映像
【问题讨论】:
该行出错:echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 关于最后一个错误,在“脚本后”中,它说没有找到sudo
。您是否尝试将其从 sudo docker logout
中删除?
【参考方案1】:
有几个错误,但整体管道看起来不错。
-
您不能在没有运行代理的情况下使用
ssh-add
如果之后您明确忽略将存储在known_hosts
下的密钥,为什么还要手动创建 .ssh 文件夹?
使用StrictHostKeyChecking=no
很危险,完全不推荐。
在before_script
上添加以下内容:
before_script:
- eval `ssh-agent`
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- ssh-keyscan -H 18.0.0.82 >> ~/.ssh/known_hosts
另外,不要在您的ubuntu
用户上使用sudo
,最好将其添加到docker
组或通过SSH 连接到docker
组中的用户。
如果您的 EC2 实例中还没有 docker
组,现在是配置它的好时机:
访问您的 EC2 实例并创建 docker
组:
$ sudo groupadd docker
将ubuntu
用户添加到docker
组:
$ sudo usermod -aG docker ubuntu
现在将您的 script
更改为:
script:
- echo $CI_REGISTRY_PASSWORD > docker_password
- scp docker_password ubuntu@18.0.0.82:~/tmp/docker_password
- ssh ubuntu@18.0.0.82 "cat ~/tmp/docker_password | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY; docker pull $CI_REGISTRY_IMAGE$tag; cd /home/crud_app; docker-compose up -d; docker logout; rm -f ~/tmp/docker_password"
另外,请记住,在 after_script
中,您不在 EC2 实例中,而是在运行器映像中,因此您不需要 logout
,但最好杀死 SSH 代理。
最后的工作
deploy:
stage: deploy
before_script:
- eval `ssh-agent`
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- ssh-keyscan -H 18.0.0.82 >> ~/.ssh/known_hosts
script:
- echo $CI_REGISTRY_PASSWORD > docker_password
- scp docker_password ubuntu@18.0.0.82:~/tmp/docker_password
- ssh ubuntu@18.0.0.82 "cat ~/tmp/docker_password | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY; docker pull $CI_REGISTRY_IMAGE$tag; cd /home/crud_app; docker-compose up -d; docker logout; rm -f ~/tmp/docker_password"
after_script:
- kill $SSH_AGENT_PID
- rm docker_password
rules:
- if: $CI_COMMIT_BRANCH
exists:
- Dockerfile
【讨论】:
请解释一下这个脚本我没明白这里发生了什么“-scp docker_password ubuntu@18.0.0.82:~/tmp/docker_password” 您试图通过stdin
在登录中传递密码,但标准输入上没有任何内容。所以我把密码写在文件docker_password
中,然后我用scp
把它复制到EC2实例上。然后在登录时,我使用cat
读取该文件的内容,并将输出通过管道传送到docker login
命令。以上是关于用于在 AWS EC2 中构建和部署 docker 映像的 CI/CD 脚本的主要内容,如果未能解决你的问题,请参考以下文章
AWS - ECS - 如何在现有 ECS(带有 1 个 EC2)实例上重新部署更新的 Docker 映像?
AWS EC2+Docker+JMeter构建分布式负载测试基础架构