使用GitHub+Travis-CI+Docker打造自动化流水线
全文采用的是阿里云的ESC服务器,系统是CentOS 7
示例项目是NodeJS编写,本文主要是Docker的使用,在文章前2/3都是Docker命令介绍,最后我们会完成一个自动化的示例。
准备
注册账号
- 
GitHub账号
发布项目到GitHub
 - 
Travis-CI账号
监听GitHub上项目改变,将其打包发布到DockerHub
 - 
DockerHub账号
Travis-CI将项目发布到DokcerHub时需要登陆DockerHub账号
 
以上账号自行注册
关于如何让Travis-CI监听到GitHub上项目的改变,请参考这篇文章
安装环境
- 
Git环境
 - 
Docker环境
安装请参考官方文档
安装完成后,运行下面的命令,验证是否安装成功。
$ docker version # 或者 $ docker infoDocker 需要用户具有 sudo 权限,为了避免每次命令都输入
sudo,可以把用户加入 Docker 用户组(如果你是root用户的话就不需要了)$ sudo usermod -aG docker $USERDocker 是服务器----客户端架构。命令行运行
docker命令的时候,需要本机有 Docker 服务。如果这项服务没有启动,可以用下面的命令启动,这是Linux下启动服务方式。# service 命令的用法 $ sudo service docker start # systemctl 命令的用法 $ sudo systemctl start docker 
正文
了解Docker
首先学习下Docker的两个核心知识点
container(容器)和image(镜像)
Docker的整个生命周期由三部分组成:镜像(image)+容器(container)+仓库(repository)
每台宿主机(电脑),他下载好了Docker后,可以生成多个镜像,每个镜像,可以创建多个容器。发布到仓库(比如DockerHub)时,以镜像为单位。可以理解成:一个容器就是一个独立的虚拟操作系统,互不影响,而镜像就是这个操作系统的安装包。想要生成一个容器,就用安装包(镜像)生成一次,这就是Docker的核心概念。
# 列出本机的所有 image 文件。
$ docker image ls
# 删除 image 文件
$ docker image rm [imageName]
image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,为了方便共享,image 文件制作完成后,可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。
image
国内连接 Docker 的官方仓库很慢,还会断线,需要将默认仓库改成国内的镜像网站
推荐使用官方镜像 registry.docker-cn.com 。下面是 CentOS 系统的默认仓库修改方法,其他系统的修改方法参考官方文档。
打开/etc/default/docker文件(需要sudo权限),在文件的底部加上一行,如果没有该文件可以自己创建。
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"
然后,重启 Docker 服务。
$ sudo service docker restart
现在就会自动从镜像仓库下载 image 文件了。
container
image 文件生成的容器实例,本身也是一个文件,称为容器文件。也就是说,一旦容器生成,就会同时存在两个文件: image 文件和容器文件。而且关闭容器并不会删除容器文件,只是容器停止运行而已。
# 列出本机正在运行的容器
$ docker container ls
# 列出本机所有容器,包括终止运行的容器
$ docker container ls --all
上面命令的输出结果之中,包括容器的 ID。很多地方都需要提供这个 ID,
使用docker container kill 命令可终止容器运行
$ docker container kill [containID]
终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm删除。
$ docker container rm [containerID]
运行上面的命令之后,再使用docker container ls --all命令,就会发现被删除的容器文件已经消失了。
Dockerfile 文件
学会使用 image 文件以后,接下来的问题就是,如何可以生成 image 文件?如果你要推广自己的软件,势必要自己制作 image 文件,这就需要用到 Dockerfile 文件。它是一个文本文件,用来配置 image。Docker 根据 该文件生成二进制的 image 文件。
下面通过一个实例,介绍什么是 Dockerfile 文件。
实例
下面我以 这个项目 为例,介绍什么是 Dockerfile 文件,实现让用户在 Docker 容器里面运行 Koa 框架。
在你的服务器上克隆该项目(如果没有Git环境记得安装)
$ git clone https://github.com/RopeHuo/travis-ci
$ cd travis-ci
.dockerignore文件
.git
node_modules
npm-debug.log
上面代码表示,这三个路径要排除,不要打包进入 image 文件。如果你没有路径要排除,这个文件可以不要
Dockerfile文件
# 该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node。
FROM node:8.4
# 将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录。
COPY ./ /app
# 指定接下来的工作路径为/app。
WORKDIR /app
# 在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。
RUN npm install --registry=https://registry.npm.taobao.org
# 将容器 3000 端口暴露出来, 允许外部连接这个端口。
EXPOSE 3000
# 这一行表示等运行image时在shell中自动输入的命令,不用我们自己再去node文件了。
CMD node hello.js
现在我们服务器上有Dokcer环境,我们通过下面的命令创建image文件
# -t参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest。
$ docker image build -t travis-ci ./
# 或者
$ docker image build -t travis-ci:0.0.1 ./
如果运行成功,就可以看到新生成的 image 文件travis-ci了。
$ docker image ls
生成容器
docker container run命令会从 image 文件生成容器。
# 3000端口是上面Dockerfile文件中暴露的,8000端口是自定义的可以通过外网访问
# -p参数:容器的 3000 端口映射到本机的 8000 端口
# -it参数:容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器
# travis-ci:0.0.1:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)
# /bin/bash:容器启动以后,内部第一个执行的命令。这里是启动 Bash,保证用户可以使用 Shell
# /bin/bash也属于CMD命令他会覆盖我们Dockerfile文件中的CMD命令,两者只能选一
$ docker container run -p 8000:3000 -it travis-ci /bin/bash
# 或者
$ docker container run -p 8000:3000 -it travis-ci:0.0.1 /bin/bash
如果一切正常,运行上面的命令以后,就会返回一个命令行提示符。
[你的服务器名称]:/app#
这表示你已经在容器里面了,返回的提示符就是容器内部的 Shell 提示符。执行下面的命令。
node hello.js
这时,Koa 框架已经运行起来了。打开浏览器,访问 [你的域名/ip]:8000,网页显示"hello world"
这个例子中,Node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射(map)。
现在,在容器的命令行,按下 Ctrl + c 停止 Node 进程,然后按下 Ctrl + d (或者输入 exit)退出容器。此外,也可以用docker container kill终止容器运行。
# 列出所有容器,不加 -a 仅列出正在运行的,像退出了的或者仅仅只是创建了的就不列出来
$ docker ps -a
# 在本机的另一个终端窗口,列出当前运行的容器,查出容器的 ID
$ docker container ls
# 停止指定的容器运行
$ docker container kill [containerID]
容器停止运行之后,并不会消失,用下面的命令删除容器文件。
# 查出容器的 ID
$ docker container ls --all
# 删除指定的容器文件
$ docker container rm [containerID]
CMD 命令
容器启动以后,需要手动输入命令node hello.js。我们可以把这个命令写在 Dockerfile 里面,这样容器启动以后,这个命令就已经执行了,不用再手动输入了。
FROM node:8.4
COPY ./ /app
WORKDIR /app
# RUN
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
# CMD
CMD node hello.js
上面有RUN命令和CMD命令,RUN命令与CMD命令的区别在哪里?简单说,RUN命令在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;CMD命令则是在容器启动后执行。另外,一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令。
注意,指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否则它会覆盖Dockerfile中的CMD命令。现在,启动容器可以使用下面的命令。
# 这里多了一个--rm,意思是在容器终止运行后自动删除容器文件。
$ docker container run --rm -p 8000:3000 -it travis-ci:0.0.1
发布image
手动发布
首先,去 hub.docker.com 或 cloud.docker.com 注册一个账户。然后,用下面的命令登录。
$ docker login
接着,为本地的 image 标注用户名和版本。
$ docker image tag [image名称] [你的用户名]/[仓库名]:[标签]
# 例子
$ docker image tag travis-ci:0.0.1 rope/travis-ci:0.0.1
也可以不标注用户名,重新构建一下 image 文件即可。
# 记得进入项目目录后再操作
$ docker image build -t [username]/[repository]:[tag] ./
最后,发布 image 文件。
$ docker image push [username]/[repository]:[tag]
发布成功以后,登录 hub.docker.com,就可以看到已经发布的 image 文件。
自动发布
我们使用gitHub+travis+docker来形成一套完整的自动化流水线
只要我们push新的代码到gitHub上,自动帮我们构建出新的代码发布到DockerHub,然后我们拉取新的镜像即可
首先我们先进入 Travis CI 官网配置,注册绑定自己的gitHub账号,然后在左侧将自己需要git push后自动构建镜像的仓库加入可参考这篇文章
我们继续使用上面用到的travis-ci项目,为了验证我们下面的操作是成功的可以将项目中的hello.js显示的hello world改成其他内容。
查看 .travis.yml 文件
language: node_js
node_js:
  - '12'
services:
  - docker
before_install:
  - npm install
script:
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
  - docker build -t mufengsm/travis-ci:latest .
  - docker push mufengsm/travis-ci:latest
注意 :mufengsm/travis-ci应该换成你的用户名/包名,再push代码
每次push代码到GitHub,Travis-CI都会下载,然后根据package.json文件下载所需包,再登陆DockerHub账户,再打包并发布到DockerHub,这样你下载的镜像就是有最新的代码。
打开travis-ci中所监听GitHub项目的设置页面,然后添加两个环境变量,这个用户名和密码和你的DockerHub账户是对应的:
DOCKER_USERNAME和DOCKER_PASSWORD
特别提示:这里的Docker容器,想要后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如tcp,ping,node),就是会自动退出的,通过 docker ps -a 可以看到容器关闭的原因
当配置成功,代码被推送到GitHub上后,travis-ci帮我们自动构建发布新镜像
一定要学会使用: docker ps -a 查看容器的状态
至此,发布,自动构建镜像已经完成
拉取新的镜像
正式开始拉取镜像,启动容器
我们刚才发布的镜像名称是:mufengsm/travis-ci
清除镜像和容器
如果在此之前你创建了很多镜像和容器,一个个删除又太麻烦,下面的命令可以帮到你。
# docker中 启动所有的容器命令
docker start $(docker ps -a | awk '{ print $1}' | tail -n +2)
#docker中 关闭所有的容器命令
docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
#docker中 删除所有的容器命令
docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)
#docker中 删除所有的镜像
docker rmi $(docker images | awk '{print $3}' |tail -n +2)
#tail -n +2 表示从第二行开始读取
然后使用:
$ docker image pull mufengsm/travis-ci:latest
拉取镜像,这时候需要下载,拉取完成后,使用docker images
可以看到mufengsm/travis-ci:latest镜像已经存在了
我们使用
# --rm参数,在容器终止运行后自动删除容器文件。
$ docker container run --rm -p 8000:3000 -it mufengsm/travis-ci:latest
创建这个镜像的容器,并且绑定在端口号8000上
浏览器输入 [你的域名/ip]:8000 发现,访问成功。
最后
我们再梳理下整个流程,创建项目,创建Dockerfile文件,创建travis.yml文件,发布到GitHub,Travis-CI监听项目,自动打包发布到DockerHub,拉取新的镜像,再运行。
参考文章
文章都是本人学习时的笔记整理,希望看完后能对您有所帮助,欢迎大家提意见,多多交流。
也有些文章是转载的,如果存在转载文章且没有标注转载地址的,请与我联系,马上处理。
自由转载-非商用-非衍生-保持署名。
                    
                
                
            
        
浙公网安备 33010602011771号