如何使用Docker和GitLab构建CI/CD Pipeline?
2018-10-22 07:44
811 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/83314522
前提要求
在开始之前,你需要确保:
关于GitLab的CI/CD
——来自GitLab文档中的描为GitLab的runner创建SSH密钥
我们将在Docker容器中通过SSH连接我们的服务器,这就意味着我们不能输入用户密码(即非交互式登录),因此我们需要在本地计算机中创建无密码的SSH密钥对。通常我会创建一个2048字节的RSA密钥,因为这足够安全。
[/code]输入以上命令,跟随创建步骤,如果对创建步骤有疑问,使用man ssh-key。记住不要为密钥对设置密码。创建完成后,我们需要把私钥导入我们的服务器:
[/code]现在你可以尝试通过以下命令连接:
[/code]连接过程应该不会让你输入密码。这个私钥我们后面会使用到。
选择Dockerfile
Pipleline的配置
我的配置文件如下:
[/code]让我们逐行看看配置文件的每一步都在做什么。
[/code]这行将告诉runner从Docker Hub上拉取并运行最新版本的容器。你可以在这里设置你想要使用的镜像,但别忘了给镜像安装OpenSSH和LFTP。
[/code]这行设置了pipeline的job名字,创建一个job必须设置这行内容。
[/code]这行设置了job的stage名字,如果你需要运行多个stage,例如“backup”、“build”、“deploy”等,stage名字将帮助你识别当前Pipeline处于什么状态。由于我不需要其他stage,所以我只用了一个job,并且这个job只有一个stage。对于job和stage的名字可以任意设置,例如你的job可以叫“ASDF”,stage可以叫“GHJK”,不过如果你有多个stage,你肯定需要鉴别不同的stage,因此我建议还是规范化这些名字。
[/code]这行表示Pipeline只有当你repo的master分支收到一个更新(例如git merge)时才会被触发。因此,我建议开发使用其他分支(例如development、wip等),然后使用master分支作为“产品分支”。
[/code]这行表示你需要进入你的project的CI/CD配置中手动触发整个部署流程。当然,这一步是可以跳过的,只是我更喜欢手动触发Pipeline。如果去掉这行,你所选分支(本例中为master)的任何改动都会触发一次Pipeline。
[/code]这行表示如果你的Pipeline中有其他stage,当一个job中发生错误时,不允许继续执行剩余任务。这是一个可选配置。
[/code]在before_script单元设置的所有命令都会在执行主单元(main script)之前执行。如你所见,每行shell命令需要用短横线(“-“)指定。上面的命令将把我们刚刚生成的SSH私钥保存到容器默认的SSH路径下,这样我们就可以免密连接我们的服务器。
刚刚生成的私钥将作为Protected变量保存在我的project的CI/CD配置中,在GitLab的web UI上,点击Settings > CI/CD > Variables将看到这个变量。同样,我将服务器地址和部署使用的用户名(非root用户)也使用Protected变量保存。
[/code]script下的内容就是GitLab的runner执行的主单元。首先,我会连接到我的服务器将所有内容备份到一个ZIP文件中,这个ZIP文件将使用当前时间(格式为yyyy-mm-dd_hh-mm-ss)进行命名:
在将/var/www/html备份后,使用LFTP连接到我的服务器并且上传最新的repo文件。这里我用的是SFTP,FTP配置有点不一样:
[/code]使用mirror -Rnev ./ /var/www/html让LFTP上传./(我repo的根目录)下的所有文件到我服务器的/var/www/html路径下。上面部分参数的意思如下:
注意:所有在我们服务上但是不在我们repository中的文件将被删除,记住上面所述的'源'指的就是我们GitLab的repository。
最终,脚本会在shared runner的容器中删除我们的私钥(这是一个安全措施),并且输出带有当前时间的结束语句。
[/code]以上部分就是我配置文件的所有内容。在GitLab中一个成功的Pipeline执行流程如下图所示:
运行Docker镜像
Pipeline的最终状态
结论
相关链接:
原文链接:https://medium.com/@jimmyadaro/build-a-ci-cd-pipeline-with-docker-and-gitlab-f351585a5c83
阅读更多
前提要求
对Linux、Docker以及CI/CD有基本的了解。
GitLab帐号(免费计划即可)。
一台具备SSH访问权限的Linux服务器(非root用户即可)。我使用的是带有LAMP[1]技术栈的Ubuntu 16.04 LTS系统。
装有SSH和LFTP[2]的轻量级Docker镜像。
在开始之前,你需要确保:
你已经登录GitLab
你是某个project/repository的拥有者
你能够在本地机器通过Git访问这个repo进行pull和push操作
我用的是GitKraken[3],一个Git GUI工具,能够较为方面的进行Git操作。
关于GitLab的CI/CD
——来自GitLab文档中的描为GitLab的runner创建SSH密钥
我们将在Docker容器中通过SSH连接我们的服务器,这就意味着我们不能输入用户密码(即非交互式登录),因此我们需要在本地计算机中创建无密码的SSH密钥对。通常我会创建一个2048字节的RSA密钥,因为这足够安全。
$ ssh-keygen rsa -b 2048
[/code]输入以上命令,跟随创建步骤,如果对创建步骤有疑问,使用man ssh-key。记住不要为密钥对设置密码。创建完成后,我们需要把私钥导入我们的服务器:
$ ssh-copy-id -i /path/to/key user@host
[/code]现在你可以尝试通过以下命令连接:
$ ssh -i /path/to/key user@host
[/code]连接过程应该不会让你输入密码。这个私钥我们后面会使用到。
选择Dockerfile
Pipleline的配置
我的配置文件如下:
image: jimmyadaro/gitlab-ci-cd:latest
Deploy:
stage: deploy
only:
— ‘master’
when: manual
allow_failure: false
before_script:
#Create .ssh directory
— mkdir -p ~/.ssh
#Save the SSH private key
— echo “$SSH_PRIVATE_KEY” > ~/.ssh/id_rsa
— chmod 700 ~/.ssh
— chmod 600 ~/.ssh/id_rsa
— eval $(ssh-agent -s)
— ssh-add ~/.ssh/id_rsa
script:
#Backup everything in /var/www/html/
— ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa $USERNAME@$HOST “zip -q -r /var/backups/www/01-Deploy-$(date +%F_%H-%M-%S).zip /var/www/html/”
#Deploy new files to /var/www/html
— lftp -d -u $USERNAME, -e ‘set sftp:auto-confirm true; set sftp:connect-program “ssh -a -x -i ~/.ssh/id_rsa”; mirror -Rnev ./ /var/www/html — ignore-time — exclude-glob .git* — exclude .git/; exit’ sftp://$HOST
— rm -f ~/.ssh/id_rsa
— ‘echo Deploy done: $(date “+%F %H:%M:%S”)’
[/code]让我们逐行看看配置文件的每一步都在做什么。
image: jimmyadaro/gitlab-ci-cd:latest
[/code]这行将告诉runner从Docker Hub上拉取并运行最新版本的容器。你可以在这里设置你想要使用的镜像,但别忘了给镜像安装OpenSSH和LFTP。
Deploy:
[/code]这行设置了pipeline的job名字,创建一个job必须设置这行内容。
stage: deploy
[/code]这行设置了job的stage名字,如果你需要运行多个stage,例如“backup”、“build”、“deploy”等,stage名字将帮助你识别当前Pipeline处于什么状态。由于我不需要其他stage,所以我只用了一个job,并且这个job只有一个stage。对于job和stage的名字可以任意设置,例如你的job可以叫“ASDF”,stage可以叫“GHJK”,不过如果你有多个stage,你肯定需要鉴别不同的stage,因此我建议还是规范化这些名字。
only:
— ‘master’
[/code]这行表示Pipeline只有当你repo的master分支收到一个更新(例如git merge)时才会被触发。因此,我建议开发使用其他分支(例如development、wip等),然后使用master分支作为“产品分支”。
when: manual
[/code]这行表示你需要进入你的project的CI/CD配置中手动触发整个部署流程。当然,这一步是可以跳过的,只是我更喜欢手动触发Pipeline。如果去掉这行,你所选分支(本例中为master)的任何改动都会触发一次Pipeline。
allow_failure: false
[/code]这行表示如果你的Pipeline中有其他stage,当一个job中发生错误时,不允许继续执行剩余任务。这是一个可选配置。
before_script:
#Create .ssh directory
— mkdir -p ~/.ssh
#Save the SSH private key
— echo “$SSH_PRIVATE_KEY” > ~/.ssh/id_rsa
— chmod 700 ~/.ssh
— chmod 600 ~/.ssh/id_rsa
— eval $(ssh-agent -s)
— ssh-add ~/.ssh/id_rsa
[/code]在before_script单元设置的所有命令都会在执行主单元(main script)之前执行。如你所见,每行shell命令需要用短横线(“-“)指定。上面的命令将把我们刚刚生成的SSH私钥保存到容器默认的SSH路径下,这样我们就可以免密连接我们的服务器。
刚刚生成的私钥将作为Protected变量保存在我的project的CI/CD配置中,在GitLab的web UI上,点击Settings > CI/CD > Variables将看到这个变量。同样,我将服务器地址和部署使用的用户名(非root用户)也使用Protected变量保存。
script:
#Backup everything in /var/www/html/
— ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa $USERNAME@$HOST “zip -q -r /var/backups/www/01-Deploy-$(date +%F_%H-%M-%S).zip /var/www/html/”
#Deploy new files to /var/www/html
— lftp -d -u $USERNAME, -e ‘set sftp:auto-confirm true; set sftp:connect-program “ssh -a -x -i ~/.ssh/id_rsa”; mirror -Rnev ./ /var/www/html — ignore-time — exclude-glob .git* — exclude .git/; exit’ sftp://$HOST
— rm -f ~/.ssh/id_rsa
— ‘echo Deploy done: $(date “+%F %H:%M:%S”)’
[/code]script下的内容就是GitLab的runner执行的主单元。首先,我会连接到我的服务器将所有内容备份到一个ZIP文件中,这个ZIP文件将使用当前时间(格式为yyyy-mm-dd_hh-mm-ss)进行命名:
— ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa $USERNAME@$HOST “zip -q -r /var/backups/www/01-Deploy-$(date +%F_%H-%M-%S).zip /var/www/html/”
在将/var/www/html备份后,使用LFTP连接到我的服务器并且上传最新的repo文件。这里我用的是SFTP,FTP配置有点不一样:
— lftp -d -u $USERNAME, -e ‘set sftp:auto-confirm true; set sftp:connect-program “ssh -a -x -i ~/.ssh/id_rsa”; mirror -Rnev ./ /var/www/html — ignore-time — exclude-glob .git* — exclude .git/; exit’ sftp://$HOST
[/code]使用mirror -Rnev ./ /var/www/html让LFTP上传./(我repo的根目录)下的所有文件到我服务器的/var/www/html路径下。上面部分参数的意思如下:
-u设置了我们sftp://$HOST的SSH用户名。
-e用于设置执行命令(使用单引号进行配置)。
-R用于设置reverse mirror。
-n表示只上传新的文件。
-e用于删除在我们源中不存在的文件。
-v用于配置verbose日志。
ignore-time将在决定是否下载时忽略时间。
exclude-glob .git`将会排除任何目录中匹配`.git的所有文件(例如.gitignore以及.gitkeep)。你可以在这里设置其他文件匹配方式。
exclude .git/这个配置将会保证不上传我们repo中的git文件。
exit将会停止LFTP和SSH执行。
注意:所有在我们服务上但是不在我们repository中的文件将被删除,记住上面所述的'源'指的就是我们GitLab的repository。
最终,脚本会在shared runner的容器中删除我们的私钥(这是一个安全措施),并且输出带有当前时间的结束语句。
— rm -f ~/.ssh/id_rsa
— ‘echo Deploy done: $(date “+%F %H:%M:%S”)’
[/code]以上部分就是我配置文件的所有内容。在GitLab中一个成功的Pipeline执行流程如下图所示:
运行Docker镜像
Pipeline的最终状态
结论
相关链接:
https://en.wikipedia.org/wiki/LAMP_%28software_bundle%29
https://lftp.yar.ru/
https://www.gitkraken.com/
https://hub.docker.com/r/jimmyadaro/gitlab-ci-cd/
https://docs.gitlab.com/ce/ci/yaml/
原文链接:https://medium.com/@jimmyadaro/build-a-ci-cd-pipeline-with-docker-and-gitlab-f351585a5c83
阅读更多
相关文章推荐
- 如何使用GitLab和Rancher构建CI/CD流水线–Part 1
- 如何使用GitLab和Rancher构建CI/CD流水线 – Part 2
- 如何使用GitLab和Rancher构建CI/CD流水线
- 如何使用GitLab和Rancher构建CI/CD流水线–Part 1
- 如何使用GitLab和Rancher构建CI/CD流水线 – Part 2
- 如何使用Dockerfile构建镜像
- 如何使用Docker构建运行时间较长的脚本
- 如何使用Dockerfile构建镜像
- Docker学习笔记(3)-- 如何使用Dockerfile构建镜像
- Docker如何使用Dockerfile构建镜像
- 从CI到CD,使用Docker技术实现每日十次发布,来自麻袋理财首席架构师王天青的分享
- Docker学习笔记(3)-- 如何使用Dockerfile构建镜像
- Docker学习笔记(3)-- 如何使用Dockerfile构建镜像
- 如何使用Dockerfile构建镜像
- 从CI到CD,使用Docker技术实现每日十次发布,来自麻袋理财首席架构师王天青的分享
- 关于如何使用Docker构建PHP的开发环境
- 如何使用Dockerfile构建镜像
- 使用Jenkins Pipeline插件和Docker打造容器化构建环境
- Docker学习笔记(3)-- 如何使用Dockerfile构建镜像