数人云今天带来的文章将分享如何用Docker实现PHP命令行程序的CI/CD过程当中总体思路以及须要注意哪些问题。php
6月10日,《DevOps&SRE超越传统运维之道》的话题将在北京延续,四位业界大牛技术齐聚,结合传统运维现状及实践案例,讲述DevOps&SRE的超越之道。点击便可报名。mysql
内容要点:laravel
使用Jet设置环境并在本地运行测试git
配置Codeship Pro每次新代码提交时,自动运行测试github
上一步的测试经过后,自动将更新部署到服务器sql
应用程序和测试套件已经在本地运行,下一步要作的是创建一些持续集成系统。虽然能够设置服务器来执行此操做,但这个过程工做量略大,所以推荐一个像Codeship Pro的服务。docker
代码提交到Codeship测试前,建议先安装其本地版本的持续集成平台:Jet。这会更快地推动工做,下面示例配置文件中,须要根据应用的实际状况,作出相应调整。shell
安装Jet后,在项目的根目录中建立两个新文件——数据库
1)codeship-services.yml –docker-compose.yml文件的变种,适用于Codeship安全
2)codeship-steps.yml – 在持续集成过程当中,命令和顺序的说明
codeship-services.yml文件与 docker-compose.yml几乎同样。内容以下:
version: "2.0" services: # PHP Application app: build: . links: - database encrypted_env_file: .env.encrypted command: cron -f # Database database: image: mariadb encrypted_env_file: .env.encrypted # Composer composer: image: composer/composer volumes: - ./:/app
codeship-steps.yml内容以下,这个文件在例子里很简单,按顺序执行这些的命令(一个接一个地)就好。若是应用程序容许,也能够并列地跑某几个步骤:
-type: serial steps: -service: composer command: install -service: app command: bash docker/codeship-run.sh
为了确保应用程序容器和数据库容器已启动,能够看到codeship-steps.yml文件调用了一个还没有建立的shell脚本。若数据库迁移,说明测试经过。把脚本放在 ./docker/codeship-run.sh ,内容以下:
#!/usr/bin/env bash ## Ensure that the database is up and running function test_database { mysqladmin -h"$DB_HOST"-u"$DB_USERNAME"-p"$DB_PASSWORD"ping } count=0 until( test_database ) do ((count++)) ## This will check up to 100 times. if[${count}-gt 100] then echo"Services didn't become ready in time" exit1 fi ## And the script waits one second between each try sleep1 done ## Create the database mysql -h"$DB_HOST"-u"$DB_USERNAME"-p"$DB_PASSWORD"-e 'CREATE DATABASE IF NOT EXISTS laravel' ## Run migrations php artisan migrate ## Run the test suite vendor/bin/phpunit
首先,该脚本会尝试链接到数据库。Codeship软件会自动启动应用程序容器和数据库容器,但MySQL初始化须要几秒,因此必须重试该test_database()功能,直到成功链接数据库(或尝试100次)。这在Codeship的Docker文档中有更详细的概述。
一旦脚本能链接到数据库,它将建立默认数据库(数据库名为laravel)。而后会运行迁移,经过PHPUnit建立数据库表和测试套件。
最后,为了测试配置正常运行和且结果经过,用Jet来运行全部步骤:
$ jet steps
若是一切正常,那么在构建容器镜像过程当中,会看到一堆输出,运行返回一条成功消息:
{ContainerRunStdout=step_name:"serial_bash_docker/codeship-run.sh" service_name:"app"}: PHPUnit 5.7.19 by Sebastian Bergmann and contributors. {ContainerRunStdout=step_name:"serial_bash_docker/codeship-run.sh" service_name:"app"}:. 1/1(100%) Time:1.09 seconds, Memory:12.00MB OK (1test,1 assertion) {StepFinished=step_name:"serial_bash_docker/codeship-run.sh"type:STEP_FINISHED_TYPE_SUCCESS} $
若是还没有提交本地代码到GitHub或Bitbucket上。每次提交代码更改时,Codeship都自动会从私有或公共仓库中拉取代码,因此只须要设置Codeship去监视那个仓库。
在Codeship中建立一个新项目,并将其链接到仓库:
跳出提示框时,选择Codeship Pro作为项目类型。
如今项目已经连接到Codeship。下次提交代码时,Codeship将会编译且使用与本地相同的codeship-steps.yml来运行。此时惟一的问题是使用本地的 .env文件,此文件不会提交到代码仓库,不过有个简单方法来设置环境变量且又不会影响安全性。
由于最好的作法是不要将.env文件推送到持续集成服务器,因此须要提出一种安全地将变量传递给Codeship方法——加密.env文件。
首先,在Codeship找到AES密钥(一般位于项目设置的常规页面中),并将其放在一个名为codeship.aes的本地根目录文件中。不要忘记将此文件添加到.gitignore,由于它是不该共享的密钥:
下一步,更新codeship-services.yml文件,让其使用加密的.env文件,而非明文.env文件:
version:"2.0" services: # PHP Application app: build: . links: - database encrypted_env_file: .env.encrypted command: cron -f # Database database: image: mariadb encrypted_env_file: .env.encrypted # Composer composer: image: composer/composer volumes: - ./:/app
使用Jet将.env文件加密成.env.encrypted,将加密后的.env.encrypted文件提交到软件仓库,而后将其推送到远程仓库:
$ jet encrypt .env.env.encrypted $ git add -A &&git commit -am "Adding codeship config" $ git push origin
Codeship正在编译代码:
也能够点击进去,查看编译详细过程和每一个步骤:
若是上述都无误地执行,最后会看到一个成功的编译结果:
虽然持续集成服务会让人知道编译和测试是否经过,但使用Codeship更大的价值在于自动化部署过程,为了作到这一点,须要作几件事情:
在服务器上手动配置和部署代码库
服务器上有一个SSH密钥,容许从代码库拉取代码
服务器上有一个脚本,用来更新代码并从新启动容器
准备齐全后,就能够构建一个部署者容器,其工做就是在编译过程结束后,登录到SSH服务器中,运行更新脚本。
这只是利用容器来部署代码的一种方法,也许并非最佳的方法。另外一个选择是使用Docker Hub等容器仓库来编译,而后直接从Docker Hub那里更新容器。Docker在生产中的最佳作法仍在探索中,这种方法更适用也相对简单。
此步骤根据主机服务提供商而有所不一样,但只要服务器知足安装了Git,Docker和Docker Compose就能够。SSH登录服务器:
建立一个新的SSH密钥
赋予SSH密钥能够从代码库读取访问
克隆代码库
设置.env文件,使用一个新的APP_KEY和数据库密码
使用docker-compose up -d –build 命令来制做镜像,而且运行容器
如今能够运行docker ps查看,当第一次在本地配置好这个项目时,能够看到一样的两个容器在运行。
如今在本地版本的代码中,添加一个shell脚本,该脚本将从仓库中获取更新的代码,并重启容器:
#!/usr/bin/env bash ## Pull the latest code git pull origin master ## Rebuild the containers docker-compose up -d --build ## Run migrations docker exec dockerphpcliexample_app_1 php artisan migrate --force
文件名叫deploy.sh 位于docker/文件夹中。
此时,要确保文件位于服务器上,所以提交代码到代码库,又将其从服务器中拉出。经过在服务器上运行命令: $ bash docker/deploy.sh ,并确保容器仍然工做。
综上所述,在编译和测试结束后,如今须要一个容器在Codeship的CI服务器远程运行此部署脚本。在仓库中建立一个名为deployer/ 的新目录,里面包含 Dockerfile文件,.env文件和execute.sh文件。
Dockerfile:
FROM alpine:latest # Install openssh RUN apk update && apk add openssh # Prep for the ssh key RUN mkdir-p "$HOME/.ssh" RUN touch$HOME/.ssh/id_rsa RUN chmod600$HOME/.ssh/id_rsa # Add the shell script COPY execute.sh execute.sh CMD sh execute.sh
.env:
USER=<SERVER_SSH_USERNAME> HOST=<SERVER_HOST> PRIVATE_SSH_KEY=<SSH_KEY (with linebreaks replaced with `\n`)>
execute.sh:
#!/usr/bin/env bash echo-e $PRIVATE_SSH_KEY>>$HOME/.ssh/id_rsa ssh-t -oStrictHostKeyChecking=no $USER@$HOST"cd docker-php-cli-example && sh docker/deploy.sh"
这个容器将使用.env文件中的环境变量,SSH登录到服务器运行部署脚本。
为了让Codeship知道部署者容器,把它添加到codeship-services.yml文件中:
# Deployer deployer: build: ./deployer encrypted_env_file: deployer/.env.encrypted codeship-steps.yml 文件: -service: deployer command: sh execute.sh
加密deployer/.env 文件,这样能够提交到代码库,而且不会暴露服务器的SSH密钥。正如对主代码库那样,用jet来加密.env文件:
$ jet encrypt deployer/.env deployer/.env.encrypted
最后,把更新的代码推到github仓库,确保Codeship成功地编译和部署了代码:
原文地址: https://blog.codeship.com/add...
活动推荐:
Meetup北京|DevOps&SRE超越传统运维之道
DevOps&SRE超越传统之道北京站来啦!6月10日,四位业界大牛技术齐聚,结合传统运维现状及实践案例,讲述DevOps&SRE的超越之道。