使用Compose和Machine实现本地与云端的同步部署与管理
【前言】
Docker 1.6发布了,Compose和Machine都在更新之列。本文具体说明了如何使用这两个组件来实现本地与云端的同步部署与管理。
Docker是个强大工具,用于启动隔离的、可重复生产的应用环境容器。本文侧重讲述如何为本地开发容器化Flask应用,同时使用Docker Compose和Docker Machine将应用交付到云主机提供商中。
本地设置
与Docker(v1.6.0)一起,我们将使用:
- Docker Compose(v1.2.0),即此前的fig,用于将一个多容器应用编排成一个单一应用。
- Docker Machine(v0.2.0)用于在本地和云端创建Docker主机。
检验一下安装是否成功:
$ docker-machine --version docker-machine version 0.2.0 (8b9eaf2) $ docker-compose --version docker-compose 1.2.0
然后,从此仓库克隆项目,或按该仓库的项目结构创建你自己的项目:
├── copy.sh ├── docker-compose.yml ├── nginx │ ├── Dockerfile │ └── sites-enabled │ └── flask_project └── web ├── Dockerfile ├── app.py ├── config.py ├── create_db.py ├── models.py ├── requirements.txt ├── static │ ├── css │ │ ├── bootstrap.min.css │ │ └── main.css │ ├── img │ └── js │ ├── bootstrap.min.js │ └── main.js └── templates ├── _base.html └── index.html
这样就为容器启动和运行做好了准备。现在进入Docker Machine。
Docker Machine
要启动Docker Machine,只需简单地运行:
$ docker-machine create -d virtualbox dev; INFO[0000] Creating CA: /Users/michael/.docker/machine/certs/ca.pem INFO[0000] Creating client certificate: /Users/michael/.docker/machine/certs/cert.pem INFO[0001] Downloading boot2docker.iso to /Users/michael/.docker/machine/cache/boot2docker.iso... INFO[0035] Creating SSH key... INFO[0035] Creating VirtualBox VM... INFO[0043] Starting VirtualBox VM... INFO[0044] Waiting for VM to start... INFO[0094] "dev" has been created and is now the active machine. INFO[0094] To point your Docker client at it, run this in your shell: $(docker-machine env dev) $ $(docker-machine env dev) create命令为Docker开发设置了一台“machine”(名为dev)。实际上,它下载了boot2docker,并启动了一个运行Docker的虚拟机。 运行如下命令来查看当前运行的Machine: $ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM dev * virtualbox Running tcp://192.168.99.100:2376
接下来,让我们使用Docker Compose来启动容器,让Flask应用及Postgres数据库启动并运行起来。
Docker Compose
来看一眼docker-compose.yml文件:
web: restart: always build: ./web expose: - "8000" links: - postgres:postgres volumes: - /usr/src/app env_file: .env command: /usr/local/bin/gunicorn -w 2 -b :8000 app:app nginx: restart: always build: ./nginx/ ports: - "80:80" volumes: - /www/static links: - web:web data: restart: always image: postgres:latest volumes: - /var/lib/postgresql command: true postgres: restart: always image: postgres:latest volumes_from: - data ports: - "5432:5432"
这里,我们定义了四个服务:web、 nginx、 postgres和 data。
- 首先,web服务是通过Dockerfile的指令在“web”目录中构建的,在此设置了Python环境,安装了必要软件,并将Flask应用运行于8000端口。这个端口会被转发到宿主环境(比如Docker Machine)的80端口上。该服务还将.env文件中定义的环境变量添加到了容器里。
- nginx服务作为反向代理用于转发请求到Flask应用或静态文件上。
- 下一个,postgres服务构建于Docker Hub的官方PostgreSQL镜像,安装了Postgres并将服务器运行于默认的5432端口上。
- 最后,请注意有一个单独的卷容器data用于存储数据库数据。这确保了即便Postgres容器被完全地销毁,数据仍然存在。
在构建镜像前,我们需要将静态文件从“web/static”目录复制到“nginx/static”中,因为nginx Dockerfile是从“nginx”目录中添加静态文件目录的。要这么做,只需要简单地运行copy.sh脚本:
$ sh copy.sh
现在,要运行容器,只要构建镜像然后启动服务即可:
$ docker-compose build $ docker-compose up -d
去喝一杯咖啡。或是两杯。第一次运行时间会久一点。
我们还需要创建数据库表:
$ docker-compose run web /usr/local/bin/python create_db.py
打开浏览器并访问与Docker Machine关联的IP地址(docker-machine ip):
棒极了!
要查看web服务可用的环境变量,运行:
$ docker-compose run web env
要查看日志:
$ docker-compose logs
你也可以进入Postgres命令行,这是因为我们在docker-compose.yml文件中转发了它的端口到宿主环境中,可以这样添加用户/角色及数据库:
$ psql -h 192.168.99.100 -p 5432 -U postgres --password
一旦完成,通过docker-compose stop停止所有进程。
部署
在应用运行于本地的同时,我们可以使用Docker Machine将与之完全相同的环境推送到云主机提供商上。我们来部署到Digital Ocean的droplet里。
在Digital Ocean注册完成后,生成一个“个人访问令牌”,然后运行以下命令:
$ docker-machine create \ -d digitalocean \ --digitalocean-access-token=你的令牌 \ production
这将花费几分钟来准备droplet并设置一个名为production的新的Docker Machine:
INFO[0000] Creating SSH key... INFO[0001] Creating Digital Ocean droplet... INFO[0133] "production" has been created and is now the active machine. INFO[0133] To point your Docker client at it, run this in your shell: eval "$(docker-machine env production)"
现在,我们运行了两个Machine,一个本地的,一个在Digital Ocean上:
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM dev * virtualbox Running tcp://192.168.99.100:2376 production digitalocean Running tcp://104.131.107.8:2376
然后,设置production作为活动machine,并将Docker环境加载到命令行中:
$ docker-machine active production $ eval "$(docker-machine env production)"
最后,在云端再次构建Flask应用: