一个初学者尝试使用Docker和docker-compose将Rails应用程序进行Docker化
1. 总体说明
这篇文章的主题是使用Docker和docker-compose将Web应用程序容器化。
可以利用的环境如下:
Mac Book Air M2芯片
Docker版本:24.0.7
docker-compose版本:2.23.3-desktop.2
Ruby版本:3.2.2
Rails版本:7.0.6
Postgresql(数据库)版本:12
本篇文章參考以下網站:
https://docs.docker.jp/compose/rails.html
2. Docker是什么
Docker是一个用于容器类型虚拟环境的平台。
虚拟化环境在以前是可行的,被称为虚拟机,需要在主机上安装虚拟软件然后安装所需的客户机操作系统和应用程序。
在这种情况下,每个应用程序都需要一个客户机操作系统,即使在物理机内部进行虚拟化,也需要大量资源(容量)。
相比之下,Docker作为一个容器型的技术,只需要在主机操作系统上安装Docker,就能够直接运行应用程序,不像虚拟机那样需要为每个应用程序安装操作系统消耗大量容量。
创建Dockerfile。
Dockerfile是一个类似于规范文件的东西,用于确定要构建的容器的内容。根据Dockerfile构建镜像,然后基于该镜像创建容器。以下是我们在本次Web应用的Docker化中实际使用的Dockerfile的内容。
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
可以将以下这两行合并成一行:ADD Gemfile Gemfile.lock /myapp/
如果使用“mkdir”命令创建目录后,会自动进入到该目录,因此可以省略“WORKDIR /myapp”这行代码。
以下是关于Dockerfile中的描述内容的说明。
在边缘左侧写着的FROM、RUN等被称为指令,基于这些指令来创建Docker镜像。
-
- FROM:Dockerfileの最初に書かれるインストラクションで、ここに書かれているイメージがベースとなってコンテナのイメージが作成されます。ここに書かれているイメージはDockerHubと呼ばれるイメージがストックされた場所から対象のベースとなるイメージが取得されます。
-
- RUN:Linuxコマンド等指定されたコマンドを実行します。&&を使えば複数のコマンドを一行にまとめられます。
-
- &&を使わずに書くことも可能ですが、イメージ自体の容量がその分大きくなってしまうので、まとめられる部分はまとめましょう。
-
- WORKDIR:Linuxコマンドのpwdと似ており、現在いる場所を変更する時に使用します。
- ADD:ホストマシンのファイルをコンテナ内部にコピーしたり、圧縮されたファイルを解凍・展開する時に使用します。(今回は前者)
3. docker-compose是什么
Docker-compose是与Docker相关的功能,用于构建和启动多个容器的工具。
只需创建一个YAML文件并执行一个命令,即可立即启动容器。
由于Docker一次只能操作一个容器,如果需要多个容器,则需要执行相应数量的命令,非常麻烦。
而使用docker-compose,只需在YAML文件中定义每个容器的内容,一次命令操作即可启动多个容器。
4. 如何创建docker-compose.yml文件
我們將對所需的YAML文件進行實際解釋。我們將其命名為docker-compose.yml。
version: '3'
services:
db:
image: postgres:12
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
docker-compose.yml的内容如下所示。
-
- version:docker-composeのバージョンを定義します。
-
- services:定義するコンテナの名前をネストして(入れ子)記入します。今回の場合はdbとweb
-
- db:データベース用のコンテナに対して設けた名前
-
- image:イメージがストックされているDocker Hubからpostgresの12バージョンイメージを取得する
-
- environment;環境変数(PC内部の変数)を設ける。ここではDBのユーザー名とパスワード
-
- web:アプリ用のコンテナに対して設けた名前
-
- build:.(カレントディレクトリ)に存在するDockerfileを使ってコンテナを構築する
-
- command:コンテナを起動した際に実行するコマンド
-
- volumes:ホストマシンとコンテナ内部のフォルダを同期して、双方向からフォルダ内を行き来できるように設定。
-
- これにより、コンテナ内部で作成したファイルを保管しておくことができます。
-
- 通常、コンテナを停止したらコンテナ内部で作成されてデータは削除されてしまうので、必要なファイルが有る場合は同期することでデータを保管できるようにします。
-
- ports:ホストマシン側とコンテナ側とでポートを指定して解放し、ホスト側からアクセスを可能とする
-
- depends_on:webとdbのコンテナ間で依存関係を作り、コンテナの起動順序を決める。
-
- 表示例の場合、dbが先に起動してwebはその後に起動する。停止する時は逆にdbが先に停止する。
- これはDBコンテナが起動する前にWebコンテナが起動すると、Webコンテナ側が起動する時にDBに対して接続する設定処理がある場合、先にDBが起動していないとWebコンテナがエラーを出してしまう現象を避ける為に行います。
构建容器需要创建基础映像,有两种方法可供选择。
第一种方法是通过创建Dockerfile来定义容器的内容。在示例中,这适用于web容器。
第二种方法是从Docker Hub获取图像,并以此为基础创建容器。在示例中,这适用于db容器。
5. 一个具体案例
我会用Docker和docker-compose实际演示如何启动Web应用程序。
软件版本等详细信息已在初始概述中说明。
必需的文件:
– Dockerfile(使用了说明中的内容)
– docker-compose.yml(使用了说明中的内容)
– Gemfile(包含要安装的内容)
– Gemfile.lock(空文件)
在创建Gemfile时,只需指定Rails的版本。
source 'https://rubygems.org'
gem 'rails', '7.0.6'
请进入包含Dockerfile的目录并执行以下命令。
docker-compose run web rails new . --force --database=postgresql
解释命令的内容
-
- docker-compose run:docker-compose.ymlで指定したサービス一つを指定してコンテナを作成・起動
-
- 今回はwebを指定しています。
-
- rails new .:RubyのRailsというフレームワーク特有のコマンドで新しくアプリを作る際に必要なファイルを作成します。
- –force –database=postgresql:DBを強制的にPOSTGRESQLとして起動します。
通过执行上述命令,启动了web容器并执行了rails new命令,生成了启动应用所需的文件。同时,Gemfile和Gemfile.lock也被更新了。
Gemfile是在使用一种名为Ruby的编程语言时所需的文件,其中列出的Gem将被安装。Gem是一种类似于程序部件的包(也称为库),具有方便的功能。
Gemfile.lock记录了按照Gemfile安装的内容。
现在应用所需的数据已经准备齐全,可以启动下面的命令来运行。
docker-compose build
通过使用docker-compose.yml文件,您可以根据命令创建容器镜像。
由于执行了rails new命令,所以已经准备好了启动应用程序所需的Gemfile等文件,现在可以创建容器镜像了。
请在新生成的文件中添加数据库配置文件database.yml的以下内容。
default: &default
+ adapter: postgresql
encoding: unicode
+ host: db
+ username: postgres
+ password: password
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
为了使数据库也能使用在docker-compose.yml中指定的username和password进行认证,需要在数据库一侧注册相同的内容。
另外,我们将以服务名注册为db,在使用时将其作为主机名,因此也会在database.yml中进行注册。
这样就可以使用指定主机名进行通信了。
如果准备工作已经完成,然后可以使用新的指令来实际启动Web应用程序。
docker-compose up
使用已经创建的容器映像构建和启动容器。
只要执行以下命令,Web应用程序启动将全部完成。
由于无法在使用docker-compose up命令的终端中输入,因此需要启动另一个终端并在那里输入。
docker-compose run web rake db:create
如果在浏览器中连接到localhost:3000,应该会显示Rails的启动界面。
通过生成数据库,您可以确认Web应用程序的启动。
在使用 rails new 命令生成新文件时,常常会犯一个错误,即在不试图创建新的容器镜像的情况下立即开始构建容器。如果容器镜像需要的文件增加或者对 Dockerfile 或 docker-compose.yml 等进行了更改,则需要重新构建容器镜像。如果尝试启动容器而不执行此步骤,则会使用旧内容的容器镜像来启动容器,因此无法按照预期构建容器。请注意这一点。
您可以使用 docker-compose build 命令重新构建镜像,或者使用 docker-compose up –build 命令重新构建镜像并启动容器,以便对更改进行反映。
此外,当出现错误时,我们很容易认为所有错误都是由 Docker 导致的,但也可能是由其他原因引起的错误。当然,如果 Dockerfile 的编写方式或者 docker-compose.yml 的内容有错误,那么很可能是由于 Docker 相关原因而停止工作,但在这种情况下,由于内容特定于在 Docker 环境中运行 Ruby 和 Rails,也完全有可能是由于它们的原因而无法工作。希望这些信息能够对您在出现错误并在网络上搜索时有所帮助。
非常感谢您阅读到这里。
在示例部分我们介绍了实际启动web应用的命令,您能成功显示rails的起始页面吗?
如果无法显示并出现错误,请根据该错误提示解决问题,努力让rails的页面能够正常显示。
我理解有些人的开发环境可能与我不同,因此可能会出现错误。在撰写本文之前,我也遇到了各种错误,但最终解决了,所以我相信您也能达到目标。