使用 Docker Compose 将 Rails 5、Postgres、Redis、Sidekiq 和 Action Cable 应用程序 Docker 化
本文最初于 2016 年 7 月 8 日发布于:https://nickjanetakis.com/blog/dockerize-a-rails-5-postgres-redis-sidekiq-action-cable-app-with-docker-compose
完成本教程后,您将了解使用 Docker 的好处
,并能够:
- 在 5 分钟或更短的时间内在所有主要平台上安装 Docker
- 运行一个使用大量最佳实践的 Rails 5+ 示例应用程序
- 知道如何编写 Dockerfile
- 使用 Docker Compose 运行多个 Docker 容器
什么是 Docker?它有何用处?
Docker允许你将应用程序或服务及其所有依赖项打包成一个标准化单元。这个单元通常被称为 Docker 镜像。
应用程序运行所需的一切都已包含在内。Docker 镜像包含代码、运行时、系统库以及您在不使用 Docker 的情况下需要在服务器上安装的任何其他内容。
为了更好地了解 Docker 将如何影响您作为软件开发人员的日常工作,
我强烈建议您阅读我之前的一篇博客文章,它将帮助您避免使用 Docker 带来的多年混乱。
安装 Docker
我们将使用的代码库与 Docker 17.06 和 Docker Compose 1.14 兼容,并且我相信它将继续与未来版本的 Docker 兼容,因此请随意安装两者的最新版本。
更新: Docker v18.04 和 Docker Compose 1.21 一切正常!
本指南假设您已安装 Docker。如果您尚未安装
,建议您注册本文底部的免费 Docker 电子邮件课程,因为它涵盖了在 Mac、Windows 和 Linux 上安装 Docker 的各种方法。
或者,如果您想立即开始,请随时查看Docker 的安装文档。为了帮助您,我还撰写了一篇关于Docker for Mac / Windows 与 Docker Toolbox 的比较指南。
确保 Docker 和 Docker Compose 正常运行
在继续之前,您应该看到我所看到的,或者非常相似的东西:
docker --version
> Docker version 17.06.0-ce, build 02c1d87
docker-compose --version
> docker-compose version 1.14.0, build c7bdf9e
创建 Rails 应用程序
这篇博文的重点是如何将一个包含
多个活动部件的 Rails 应用程序 Docker 化。我们可以rails new
创建一个新项目并构建它,但使用现成的应用程序会更快。
我们将使用 orats 提供的基础应用程序,它是一个
用于生成自定的 Rails 项目的开源工具。
如果您想进一步了解这个基础应用的功能,我建议您阅读orats 的 README 文件。本文仅介绍 Docker 相关的部分。
现有的 Rails 应用程序怎么样?
本文非常通用,您可以将即将阅读的所有内容应用到您自己的应用程序中,而不是 orats 示例应用程序中。
您将要阅读的内容与 orats 无关。由于您事先没有这些文件,因此只需创建几个文件即可。
安装 orats
由于您很可能是一名 Ruby 开发人员,您的
工作站上已经安装了 Ruby,因此安装非常简单gem install orats
。
生成新项目
# Feel free to generate the project anywhere you want.
orats new /tmp/my_dockerized_app
在您喜欢的代码编辑器中打开项目
# Move into the project's directory
cd /tmp/my_dockerized_app
# Open the project with your favorite editor (mine is Sublime)
subl .
您可以随意使用任何您想要的编辑器,但是如果您喜欢 Sublime Text 3 并且
想要为 Rails、Docker 等配置它,那么请查看我的帖子“适用于多语言程序员的 25 个 Sublime Text 3 包”。
Docker化Rails应用程序
我们需要做一些事情来将应用程序 Docker 化。
日志记录
为了使日志功能正常运行,Docker 要求你的应用程序或
进程将日志记录到 STDOUT。这是一个非常好的想法,因为现在管理日志文件的概念
将与你的 Rails 应用程序解耦。
您可以选择让 Docker 将这些日志条目写入 syslog 或服务器上运行的其他本地服务,或者您可以将日志输出传送到第三方服务(如 Loggly)。
无论哪种情况,您都需要对 Rails 应用程序进行小幅调整:
# config/application.rb : Lines 21-24
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.log_tags = [:subdomain, :uuid]
config.logger = ActiveSupport::TaggedLogging.new(logger)
在 orats 基础项目中,我决定在文件中设置日志记录,application.rb
因为它对所有环境都是通用的。
我们只是将 Rails 设置为记录到 STDOUT,然后我们还设置自定义格式化程序以在每个日志条目中包含子域和 uuid。
我喜欢这样做,因为它使过滤日志变得非常简单——特别是
当您的应用程序规模不断扩大并且有许多活动部件时。
Docker 特定文件
项目的根目录下有几个与 Docker 相关的文件:
nick@oriath:/tmp/my_dockerized_app ⚡ ls -la
-rw-rw-r-- 1 nick nick 3507 Jul 7 10:50 .env
-rw-rw-r-- 1 nick nick 1032 Jul 7 10:50 docker-compose.yml
-rw-rw-r-- 1 nick nick 4353 Jul 7 10:50 Dockerfile
-rw-rw-r-- 1 nick nick 49 Jul 7 10:50 .dockerignore
唯一需要添加的文件是,Dockerfile
但您会发现
大多数支持 Docker 的 Web 应用程序都会有其他文件。
Dockerfile
让我们从这个开始,Dockerfile
因为要讨论其他文件
,需要对 Docker 镜像的构建方式有一点了解。
你可以将此文件视为你的 Docker 镜像蓝图或配方。运行该docker build
命令时,它将从上到下执行每一行。
它将在 Docker 镜像的上下文中运行所有这些命令。
为了更好地理解这个文件,请查看我全新的
Dive Into Docker 课程。
FROM ruby:2.4-alpine
RUN apk update && apk add build-base nodejs postgresql-dev
RUN mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --binstubs
COPY . .
LABEL maintainer="Nick Janetakis <nick.janetakis@gmail.com>"
CMD puma -C config/puma.rb
此时我们可以构建图像并且您将能够访问 Rails 应用程序,但是现在我们先避免这样做。
.dockerignore
我们首先来看一下下一个文件,即该.dockerignore
文件。
.git
.dockerignore
.byebug_history
log/*
tmp/*
当我们使用该命令将当前目录中的所有文件复制到 Docker镜像中时COPY . .
,它将复制所有内容。
这可不是个好主意,因为如果你的项目是 git repo,你肯定会有一大堆额外的数据。你应该在合理范围内尽量使用最小的 Docker 镜像。
该.dockerignore
文件与普通文件非常相似.gitignore
。它允许您
将某些文件夹或文件列入黑名单,以防止被包含。
docker-compose.yml
Docker Compose 是 Docker 官方提供的工具。它本质上是一个实用程序,可让您“编写”Docker 命令并轻松地管理多个容器。
让我们看一下这个docker-compose.yml
文件:
version: '2'
services:
postgres:
image: 'postgres:10.3-alpine'
volumes:
- 'postgres:/var/lib/postgresql/data'
env_file:
- '.env'
redis:
image: 'redis:4.0-alpine'
command: redis-server --requirepass yourpassword
volumes:
- 'redis:/data'
website:
depends_on:
- 'postgres'
- 'redis'
build: .
ports:
- '3000:3000'
volumes:
- '.:/app'
env_file:
- '.env'
sidekiq:
depends_on:
- 'postgres'
- 'redis'
build: .
command: sidekiq -C config/sidekiq.yml.erb
volumes:
- '.:/app'
env_file:
- '.env'
cable:
depends_on:
- 'redis'
build: .
command: puma -p 28080 cable/config.ru
ports:
- '28080:28080'
volumes:
- '.:/app'
env_file:
- '.env'
volumes:
redis:
postgres:
如果你想了解所有这些是如何联系在一起的, 《深入 Docker》这本书会涵盖所有内容的方方面面。很多时候,了解“为什么”比了解它是如何实现的更重要。这才是让你能够独立应用这些方法的关键。
.env
从技术上讲,该文件不是 Docker 的一部分,但它被 Docker
Compose 和 Rails 应用程序部分使用。
默认情况下,Docker Compose 将在与您的文件.env
相同的目录中查找文件。docker-compose.yml
我们可以在这里设置各种环境变量,如果您的应用程序使用 ENV 变量,您甚至可以在这里添加自定义环境变量。
COMPOSE_PROJECT_NAME=my_dockerized_app
通过将 设置COMPOSE_PROJECT_NAME
为my_dockerized_app
,Docker Compose
将自动在我们的 Docker 镜像、容器、卷和网络前添加 前缀mydockerizedapp
。
碰巧的是,Docker Compose 会从名称中去掉下划线。
此文件中还有许多其他值.env
,但大多数是
Rails 应用程序自定义的。稍后我们将介绍一些与 Docker 相关的值。
运行 Ruby on Rails 应用程序
您可以通过输入以下命令来运行所有内容:docker-compose up --build
。Docker Compose 有许多不同的子命令和标志。您肯定想亲自了解一下。
命令完成后up
,打开一个新的终端选项卡并检查为您创建的内容。
Docker 镜像
跑步docker images
:
mydockerizedapp_cable latest ... 392 MB
mydockerizedapp_sidekiq latest ... 392 MB
mydockerizedapp_website latest ... 392 MB
postgres 10.3-alpine ... 39.5 MB
redis 4.0-alpine ... 27.5 MB
ruby 2.5-alpine ... 60.7 MB
Docker Compose 自动为您拉取 Redis 和 Ruby,然后为您构建网站、sidekiq 和电缆图像。
Docker 容器
跑步docker-compose ps
:
Name State Ports
------------------------------------------------------------------------
mydockerizedapp_cable_1 ... Up 0.0.0.0:28080->28080/tcp
mydockerizedapp_postgres_1 ... Up 5432/tcp
mydockerizedapp_redis_1 ... Up 6379/tcp
mydockerizedapp_sidekiq_1 ... Up
mydockerizedapp_website_1 ... Up 0.0.0.0:3000->3000/tcp
Docker Compose 会自动为您命名容器,并附加一个,_1
因为它正在运行 Docker 镜像的 1 个实例。Docker Compose 支持扩展,但这超出了本教程的讨论范围。
我们还可以看到服务正在使用和公开哪些端口。
还有很多内容需要讨论,但以上内容已经足够了。
查看网站
如果您通过 Docker Toolbox 安装了 Docker,则需要对该文件进行 3 处快速更改。如果您正在本地运行 Docker,则现在.env
即可访问。http://localhost:3000
Docker Toolbox 用户需要对该.env
文件进行 3 处更改:
# Open the .env file and find these values:
ACTION_MAILER_HOST=localhost:3000
ACTION_CABLE_FRONTEND_URL=ws://localhost:28080
ACTION_CABLE_ALLOWED_REQUEST_ORIGINS=http:\/\/localhost*
# Replace `localhost` with your Docker Machine IP address:
ACTION_MAILER_HOST=192.168.99.100:3000
ACTION_CABLE_FRONTEND_URL=ws://192.168.99.100:28080
ACTION_CABLE_ALLOWED_REQUEST_ORIGINS=http:\/\/192.168.99.100*
Toolbox 用户需要将一些实例更改localhost
为192.168.99.100
Docker Machine 的 IP 地址。您可以通过docker-machine ip
从启用 Docker 的终端运行来确定您的 IP 地址。
这是因为您的系统上没有原生运行 Docker。这也意味着您需要http://192.168.99.100:3000
通过浏览器访问。
此时你会注意到它抛出了一个错误,提示数据库
不存在。不用担心,这是意料之中的事吧?我们还没有重置数据库。
与 Rails 应用程序交互
本篇博文将有两个目的:一是展示如何
通过 Docker 运行 Rails 命令;二是展示如何初始化 Rails 数据库。
在新的启用 Docker 的终端选项卡中运行以下两个命令
重置数据库
docker-compose exec --user "$(id -u):$(id -g)" website rails db:reset
- 如果你使用的是 OSX 或 Windows,请不要包含
--user flag
迁移数据库
docker-compose exec --user "$(id -u):$(id -g)" website rails db:migrate
- 如果你使用的是 OSX 或 Windows,请不要包含
--user flag
上述命令发生了什么?
Docker Compose 有一个exec
命令,允许你在已经运行的容器上执行命令。我们正在website
容器上运行命令。
该--user "$(id -u):$(id -g)"
标志确保命令生成的任何文件
最终exec
都归您的用户而不是 root 所有。
实时开发环境
由于我们已经设置了卷,docker-compose.yml
您将能够
积极开发您的应用程序,就像它在您的操作系统上本地运行一样。
尝试访问app/views/pages/home.html.erb
,然后对文件进行更改。
您只需保存文件并刷新浏览器即可查看更改。
关闭一切
您需要转到 Docker Compose 终端选项卡并按下CTRL+C
。然后,为了保险起见,请输入docker-compose stop
。有时 Compose 会出现错误,不会自动停止所有容器。
结论
Docker 太棒了!现在你可以在其他平台上运行你的项目,而不必担心依赖关系和特定平台的问题。
您甚至可以轻松地将项目部署到生产中。
如果您已准备好掌握 Docker,请查看“深入 Docker”课程。
文章来源:https://dev.to/nickjj/dockerize-a-rails-5-postgres-redis-sidekiq-and-action-cable-application-with-docker-compose--1ana