Docker 和 Docker Compose 的使用

安装Docker

安装官网安装教程安装完成后,在命令行输入

1
2
boot2docker init
boot2docker up

执行如上命令后,安装提示 export Docker 的相关环境变量,之后输入 docker version 查看是否启动成功

运行一个Docker Image

安装完成后就可以运行一个 docker 镜像了,命令如下

1
docker run hello_world

这个简单的命令就启动了一个 docker 的 container ,这个 container 中运行的就是 hello world 这个镜像。 从命令行的输出可以看出, docker 首先会在本地寻找 hello_world 这个镜像,如果本地没有,则去 docker 的线上 hub 仓库中拉取这个镜像,这个你就可以 docker run 任何你需要的并且在 docker 的 hub 仓库存在的镜像。

建立自己的 Docker Image

重点来了,Docker 的 hub 仓库和 Github 一样,有很多开发者贡献的开源镜像,你可以根据你的需要到 Docker Hub 查找镜像,例如我需要运行 rails app 的镜像,我去查找 rails, 发现有一个官方的 rails 镜像(很多应用都有官方镜像在 Docker Hub 中),并且他的说明里也写明了如何使用这个镜像去搭建我自己程序的镜像。
但是有时候这些已经存在的镜像不能满足我们的要求,或者我们需要将我们的应用这个打包一个我们私有的镜像的时候怎么办呢? 这个时候就需要 Dockerfile ,以下是 rails 官方的 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
FROM ruby:2.2
# see update.sh for why all "apt-get install"s have to stay as one long line
RUN apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*
# see http://guides.rubyonrails.org/command_line.html#rails-dbconsole
RUN apt-get update && apt-get install -y mysql-client postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV RAILS_VERSION 4.2.3
RUN gem install rails --version "$RAILS_VERSION"

其中 FROM RUN ENV 是 Dockerfile 的一些关键字,FROM 指明这个 Image 的基础 Image,这里是 ruby 2.2.2,因为 rails 是 ruby 的一个 web 框架,所以这个镜像基于 ruby 的镜像,这个可以省去配置 ruby 环境。如果去看 ruby 的 Dockerfile ,就会发现 ruby 基于 buildpack-deps ,而 buildpack-deps 又基于 debian 。通过这样的层级关系,可以省去大量配置环境的时间,可以利用已有的合适的镜像,通过添加一些命令,如安装一些软件,来建立自己的镜像。
RUN 后面跟随需要在命令行执行的命令,一般就是安装一些依赖包,执行一些你的程序需要执行的命令,如上面的 gem install
ENV 设置环境变量,以键值对的方式,在 Dockerfile 中调用
其它还有 ADD CMD EXPOSE ENTRYPOINT WORKDIR USER VOLUME ,具体用法可以看 Docker 的官方说明

使用 Docker Compose 搭建需要多个服务的应用环境

以 rails 应用为例,可能需要 rails 环境,database 和 redis 等应用支持,这个时候如果将他们全部聚合到一个镜像,可能并不方便,Docker Compose 就可以解决这种问题,通过简单的配置,使多个容器依次启动,并进行通信,从而运行一个 rails 应用。

安装 Docker Compose

1
2
curl -L https://github.com/docker/compose/releases/download/1.3.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

首先配置 web 应用的 Dockerfile ,以 rails 应用为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 以 rails 4.2.2 为基础 Image
FROM rails:4.2.2
# 建立 work dir
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# 安装 Gem
COPY Gemfile /usr/src/app/
COPY Gemfile.lock /usr/src/app/
RUN bundle install
# 将应用其余文件拷贝到工作目录
COPY . /usr/src/app
# 启动 sidekiq (optional)
RUN bundle exec sidekiq -d -C config/sidekiq.yml -L log/sidekiq.log

然后配置 所有需要使用到的相关服务镜像,在应用根目录下建立 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
db:
image: postgres
ports:
- "5432"
redis:
image: redis
ports:
- "6379"
web:
build: .
command: bundle exec rails s -b 0.0.0.0
volumes:
- .:/usr/src/app
ports:
- "3000:3000"
links:
- db
- redis

从上面的 yaml 文件可以看出,我们配置了 postgres 数据库, redis,以及我们自己配置完成的 web 应用,这样 Docker Compose 会启动三个 container ,分别承载 db redis web 这三个镜像,他们之间通过环境变量的配置进行通信,以 database.yml 为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: 5
username: postgres
password:
host: db
development:
<<: *default
database: development
test:
<<: *default
database: test
production:
<<: *default
database: production

上面的 host: db 就是指向 db 这个 container ,也可以以环境变量指向 db 的container

1
2
host: <%= ENV['APPNAME_DB_1_PORT_5432_TCP_ADDR'] %>
port: <%= ENV['APPNAME_DB_1_PORT_5432_TCP_PORT'] %>

这些环境变量可以通过命令 docker-compose run web env 查看, redis 的配置与 db 类似

Docker Compose 需要 Javascript runtime ,在 rails 下,在 Gemfile 中加入 therubyracer 即可

gem ‘therubyracer’, platforms: :ruby
这样就基本配置完成了,之后运行如下命令

1
2
3
4
5
6
7
8
# 创建定义的所有镜像
docker-compose build
# 迁移数据库
docker-compose run web rake db:create
docker-compose run web rake db:migrate
# 启动
docker up

执行完上面的命令,我们就可以访问一个 在 Docker 中运行 rails 应用了,但是它的地址是 boot2docker 的ip, 可以在 命令行中 输入 boot2docker ip 查看 ip 地址是多少,如 192.168.59.103 ,那我们的 rails 应用就可以通过 192.168.59.103:3000 访问了。