Skip to main content

[DevOps] Docker三剑客

Docker 三剑客介绍

为了把容器化技术的优点发挥得更好,docker 公司先后推出了三大技术:

  • docker-machine
  • docker-compose
  • docker-swarm

使用"三剑客"可以帮助我们解决 docker host 维护,多容器编排部署,多个 docker host 集群的各个难题。

Docker machine

docker 使用了 linux 的内核技术(namespace,cgroup 等),那么如果我想在 windows 或 Mac 系统上运行 docker 怎么办呢?

答案是借助虚拟机来实现,也就是说我在 windows 或 Mac 上运行一个 linux 虚拟机,再在虚拟机里运行 docker。

machine

docker-machine 就是 docker 公司官方提出的,用于在各种平台上快速创建具有 docker 服务的虚拟机的技术.

参考: https://docs.docker.com/machine/

Docker compose

用容器运行一个服务,需要使用 docker run 命令。但如果我要运行多个服务呢? 假设我要运行一个 web 服务,还要运行一个 db 服务,那么是用一个容器运行,还是用多个容器运行呢?

一个容器运行多个服务会造成镜像的复杂度提高,docker 倾向于一个容器运行一个应用。

那么复杂的架构就会需要很多的容器,并且需要它们之间有关联(容器之间的依赖和连接)就更复杂了。

这个复杂的问题需要解决,这就涉及到了容器编排的问题了。

docker-compose 就是可以做容器编排的小工具,它可以在一个文件中定义多个容器,只用一行命令就可以让一切就绪并运行。

docker-compose 安装

方法 1: 使用 pip 安装

# yum install epel-release -y
# yum install python2-pip -y
# pip2.7 install docker-compose

卸载方法:

# pip uninstall docker-compose

方法 2: 直接下载

# curl -L
"https://github.com/docker/compose/releases/download/1.24.
1/docker-compose-$(uname -s)-$(uname -m)" -o
/usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose

卸载方法:

# rm /usr/local/bin/docker-compose

安装完后验证

# docker-compose -v
docker-compose version 1.24.1, build 4667896

使用 docker-compose 的三个步骤

Docker Compose 将所管理的容器分为三层

  1. 工程(project)
  2. 服务(service)
  3. 容器(contaienr)

Docker Compose 运行的目录下的所有文件(docker-compose.yml,extends 文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。

一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。

一个服务当中可包括多个容器实例

使用 Compose 基本上分为三步:

  1. Dockerfile 定义应用的运行环境(镜像)
  2. docker-compose.yml 定义组成应用的各服务
  3. docker-compose up 构建并启动整个应用

docker compose 常见语法

docker compose 使用.yml 或.yaml 后缀

参考: https://docs.docker.com/compose/compose-file/

build

指定镜像构建时的 dockerfile 目录,格式一般为绝对路径目录或相对路径目录(dockerfile 需要命名为 Dockerfile)

build: /path/to/build/dir
或者
build: ./dir

image

指定要启动容器的镜像

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd

如果镜像不存在,compose 尝试拉它

如果指定了构建, 可以使用指定的选项构建它,并使用指定的 tag 进行标记

environment

设置镜像变量,它可以保存变量到镜像里面,也就是说启动的容器也会包含这些变量设置

environment 和 Dockerfile 中的 ENV 指令一样会把变量一直保存在镜像容器中

environment:
RACK_ENV: development
SHOW: 'true'

environment:
- RACK_ENV=development
- SHOW=true

expose

这个标签与 Dockerfile 中的 EXPOSE 指令一样,用于指定暴露的端口,但只将端口暴露给连接的服务,而不暴露给主机.

expose:
- "3000"
- "8000"

ports

映射端口,可以使用 HOST:CONTAINER 的方式指定端口,也可以指定容器端口(选择临时主机端口),宿主机会随机映射端口

ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"

restart

指定 Docker 容器的重启策略

默认值为 no ,即在任何情况下都不会重新启动容器

当值为 always 时,容器退出时总是重新启动;

当值为 on-failure 时,当出现 on-failure 报错(非正常退出,退出状态非 0),才会重启容器

当值为 unless-stopped 时, 在容器退出时总是重启容器,但是不考虑在 Docker 守护进程启动时就已经停止了的容器

restart: "no"
restart: always
restart: on-failure
restart: on-failure:3
restart: unless-stopped

volume

数据卷挂载,可以直接使用 HOST:CONTAINER 这样的格式或者使用 HOST:CONTAINER:ro 这样的格式,ro 代表数据卷是只读的

volumes:
# 只是指定一个路径,Docker 会自动在创建一个数据卷(这个路径是容器
内部的)。
- /var/lib/mysql
# 使用绝对路径挂载数据卷
- /opt/data:/var/lib/mysql
# 以Compose配置文件为中心的相对路径作为数据卷挂载到容器。
- ./cache:/tmp/cache
# 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者
/root/)。
- ~/configs:/etc/configs/:ro
# 已经存在的命名的数据卷。
- datavolume:/var/lib/mysql

depends_on

此标签解决了容器的依赖、启动先后的问题

version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: mysql

使用 docker-compose up web 启动,会先启动 redis 和 db,再启动 web

链接到其它服务的中的容器, 与 link 连接一样效果,会连接到其它服务中的容器

web:
links:
- db
- db:database
- redis

docker-compose 基础应用案例一

参考: https://docs.docker.com/compose/gettingstarted/

案例 1: wordpress 应用

1, 创建一个名为 wordpress 的 project(工程)

[root@daniel ~]# mkdir -p /doker-compose/wordpress
[root@daniel ~]# cd /doker-compose/wordpress

2, 创建 docker-compose.yml

[root@daniel wordpress]# vim docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
volumes:
- "./data:/var/lib/mysql"
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
expose:
- "3306"
wordpress:
depends_on:
- db
image: wordpress:latest
links:
- db
ports:
- "8010:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_PASSWORD: wordpress

说明:

这个应用定义了两个容器服务:db, wordpress

db 容器通过 mysql:5.7 镜像启动

  • MySQL 的数据目录挂载到当前目录./data,此目录不存在会自动创建
  • 容器重启策略为 always
  • 设置了连接 mysql 的 4 个变量

wordpress 容器通过 wordpress:latest 启动

  • 需要 db 容器先启动再启动 wordpress 容器
  • wordpress 容器要 link 连接 db 容器
  • wordpress 容器将 80 端口映射到宿主机的 8010 端口
  • 容器重启策略为 always
  • 设置连接数据库的变量

3, 启动

[root@daniel wordpress]# docker-compose up -d

如果本地没有镜像,下载的两个镜像比较大

[root@daniel wordpress]# docker images
REPOSITORY TAG IMAGE ID
CREATED SIZE
mysql 5.7 e9c354083de7
3 days ago 373MB
wordpress latest 4ba1e63bd20c
8 days ago 501MB

4, 访问

访问容器主机的 8010 端口

5, 不用了可以关闭并删除

[root@daniel wordpress]# docker-compose stop
Stopping wordpress_wordpress_1 ... done
Stopping wordpress_db_1 ... done
[root@daniel wordpress]# docker-compose rm
Going to remove wordpress_wordpress_1, wordpress_db_1
Are you sure? [yN] y 输
入y确认删除容器
Removing wordpress_wordpress_1 ... done
Removing wordpress_db_1 ... done

案例 2: haproxy 应用

1, 创建一个工程目录 haproxy

[root@daniel ~]# mkdir -p /docker-compose/haproxy
[root@daniel haproxy]# cd /docker-compose/haproxy

2, 准备 haproxy.cfg 配置文件

[root@daniel haproxy]# vim haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
stats uri /status
frontend balancer
bind 0.0.0.0:80
mode http
default_backend web_backends
backend web_backends
mode http
option forwardfor
balance roundrobin
server web1 web1:80 check
server web2 web2:80 check
server web3 web3:80 check
option httpchk GET /
http-check expect status 200

3, 创建编排脚本

[root@vm1 haproxy]# vim docker-compose.yml
web1:
image: httpd:latest
volumes:
- ./httpd1:/usr/local/apache2/htdocs/
expose:
- 80
web2:
image: httpd:latest
volumes:
- ./httpd2:/usr/local/apache2/htdocs/
expose:
- 80
web3:
image: httpd:latest
volumes:
- ./httpd3:/usr/local/apache2/htdocs/
expose:
- 80
haproxy:
image: haproxy:latest
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- web1
- web2
- web3
ports:
- "80:80"
expose:
- "80"

4, 启动应用

[root@daniel haproxy]# docker-compose up -d

5, 在挂载目录建立不同的主页用于测试

[root@daniel haproxy]# echo web1 > httpd1/index.html
[root@daniel haproxy]# echo web2 > httpd2/index.html
[root@daniel haproxy]# echo web3 > httpd3/index.html

6, 访问 http:// docker 宿主机 IP :80 验证是否负载均衡调度

访问 http:// docker 宿主机 IP :80/status 验证是否有状态页面