跳到主要内容

快速开始:compose 和 Rails

本文教你如何用 docker compose 设置和运行 Rails/PostgreSQL 应用。开始之前先安装 docker compose

定义项目

从构建应用所需的文件开始。容器内运行的应用包含了它的依赖,通过 Dockfile 文件定义依赖。Dockerfile 文件由下面部分组成

FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

将应用代码放入到镜像,怎么编写 Dockerfile 参考 Docker user guideDockerfile reference.

下一步,创建 Gemfile 文件。可以通过 rails new 创建。

source 'https://rubygems.org'
gem 'rails', '~>5'

创建 Gemfile.lock 文件用来构建 Dockerfile

touch Gemfile.lock

下一步,提供一个入口脚本用来修复 Rails 特定的问题。防止服务器在 server.pid 存在的情况下不重启。这个脚本在每次容器启动的时候执行。entrypoint.sh 文件如下:

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

最后,docker-compose.yml 是魔力发生的地方。这个文件描述了服务包含了你的应用(数据和 web 应用),如何获取 docker 镜像,网络应用如何从当前目录构建,和将这些应用连接到一起,暴露网络应用端口。

version: '3'
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db

可以使用 .yml 和 .yaml 扩展名

构建项目

这些文件准备好后,可以使用 docker-compose run 生成 rails 项目骨架:

docker-compose run web rails new . --force --no-deps --database=postgresql

首先,compose 使用 dockerfile 构建镜像里的 web 服务。然后使用镜像在容器里执行 rails new。之后你得到了个全新的应用。

查看生成的文件

$ ls -l
total 64
-rw-r--r-- 1 vmb staff 222 Jun 7 12:05 Dockerfile
-rw-r--r-- 1 vmb staff 1738 Jun 7 12:09 Gemfile
-rw-r--r-- 1 vmb staff 4297 Jun 7 12:09 Gemfile.lock
-rw-r--r-- 1 vmb staff 374 Jun 7 12:09 README.md
-rw-r--r-- 1 vmb staff 227 Jun 7 12:09 Rakefile
drwxr-xr-x 10 vmb staff 340 Jun 7 12:09 app
drwxr-xr-x 8 vmb staff 272 Jun 7 12:09 bin
drwxr-xr-x 14 vmb staff 476 Jun 7 12:09 config
-rw-r--r-- 1 vmb staff 130 Jun 7 12:09 config.ru
drwxr-xr-x 3 vmb staff 102 Jun 7 12:09 db
-rw-r--r-- 1 vmb staff 211 Jun 7 12:06 docker-compose.yml
-rw-r--r-- 1 vmb staff 184 Jun 7 12:08 entrypoint.sh
drwxr-xr-x 4 vmb staff 136 Jun 7 12:09 lib
drwxr-xr-x 3 vmb staff 102 Jun 7 12:09 log
-rw-r--r-- 1 vmb staff 63 Jun 7 12:09 package.json
drwxr-xr-x 9 vmb staff 306 Jun 7 12:09 public
drwxr-xr-x 9 vmb staff 306 Jun 7 12:09 test
drwxr-xr-x 4 vmb staff 136 Jun 7 12:09 tmp
drwxr-xr-x 3 vmb staff 102 Jun 7 12:09 vendor

如果你在 linux 系统上运行 rails new,创建的文件是 root 权限。因为容器是以 root 用户运行的。如果这样,重新设置这些文件的权限。

sudo chown -R $USER:$USER .

如果你用的是 mac 或者 windows 系统,你应该已经有了所有文件的权限。包括哪些 rails new 生成的文件。

现在你拿到了一个新的 Gemfile 文件,你需要重新构建镜像。(只有修改了 Gemfile 或者 Dockerfile 文件你才需要进行重新构建)。

docker-compose build

连接数据库

现在应用已经可以运行了。Rails 期望本地运行的数据库,你需要把数据库指向容器中的。你还需要修改数据库的用户名和密码。

修改 config/database.yml 文件为一下内容

default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password:
pool: 5

development:
<<: *default
database: myapp_development


test:
<<: *default
database: myapp_test

你现在可以通过 docker-compose up 启动应用。

docker-compose up

如果没有问题,你可以看到 postreqsl 的输出。

rails_db_1 is up-to-date
Creating rails_web_1 ... done
Attaching to rails_db_1, rails_web_1
db_1 | PostgreSQL init process complete; ready for start up.
db_1 |
db_1 | 2018-03-21 20:18:37.437 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2018-03-21 20:18:37.437 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2018-03-21 20:18:37.443 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2018-03-21 20:18:37.726 UTC [55] LOG: database system was shut down at 2018-03-21 20:18:37 UTC
db_1 | 2018-03-21 20:18:37.772 UTC [1] LOG: database system is ready to accept connections

最后你需要在另外一个终端中执行下面命令创建数据库

docker-compose run web rake db:create

下面是执行的输出

vmb at snapair in ~/sandbox/rails
$ docker-compose run web rake db:create
Starting rails_db_1 ... done
Created database 'myapp_development'
Created database 'myapp_test'

查看 Rails 的欢迎页面

现在你的应用运行在 docker 守护进程的 3000 端口上。

在 docker mac 和 windows 下可以浏览器访问 http://localhost:3000 查看。

如果使用 docker machine, 执行 docker-machine ip MACHINE_VM 查看虚拟机的 ip 地址,然后访问 Docker-Host-IP:3000

停止应用

在项目目录下运行 docker-compose down 停止运行应用。

vmb at snapair in ~/sandbox/rails
$ docker-compose down
Stopping rails_web_1 ... done
Stopping rails_db_1 ... done
Removing rails_web_run_1 ... done
Removing rails_web_1 ... done
Removing rails_db_1 ... done
Removing network rails_default

重启应用

执行 docker-compose up 重启应用。

重新构建应用

如果你修改了 Gemfile 或者 compose 文件配置,你需要重新构建。一些变更只需要执行 docker-compose up --build。一个完整的构建需要在执行 docker-compose up --build 之后再执行 docker-compose run web bundle install 来同步 Gemfile.lock 中的内容。

比如我们修改了 compose 文件中端口,不需要完全的重建。

ports: - "3001:3000"

现在你可以执行 docker-compose up --build 命令,在容器内你的应用还是运行在 3000 端口,但是在本机暴露的是 3001 端口。可以通过 http://localhost:3001 访问

更多 compose 文档

参考