请以中国本地人的方式将以下内容改述成中文,只需提供一种选项:即使现在在「Docker 是什么?」到「能够独自制作 docker-compose 文件」这一范围内也无法听懂 Docker 的工作原理
首先
有点不知不觉地开始使用Docker已经有大约4年了。
当被分配到现有项目时,只需执行命令而不必意识到Docker文件中有什么内容,而当需要自己从零开始创建时,我通常会从某处获取别人已经创建好的内容来完成。
因为这种感觉,我对docker有些模糊的了解,但对细节一窍不通。
本次是一个男人试图理解得足够可以向他人解释的文章。
希望您能在进行实践的过程中一起动手尝试,这样我会感到很开心。
目标读者
-
- これからdockerをは0から理解したい人
-
- なんとなくdocker触っちゃってて理解していない俺みたいな人
-
- (でもLinux多少知っていないと少し大変かもです)
-
- Docker, docker image, docker container, docker-composeといわれてもパッとイメージがつかない俺みたいなレベル感の人
- ※rubyとrailsをベースに解説を行いますがエッセンスとなる部分はrubyユーザーでなくても参考になる部分は多いと思います。
Docker是什么?
由于有更多解释得更好的人,所以我会简要地解释一下。

让我们实际构建Docker镜像并启动Docker容器进行尝试。
要启动Docker容器,需要有Docker镜像。
Docker镜像是Docker容器的模板。
为了创建Docker镜像,需要准备一个Dockerfile。
Dockerfile可以说是Docker镜像的”设计图纸”。
建立docker镜像
我们先在任意目录下创建一个工作目录吧。我打算在名为docker_sample的目录中进行工作。
mkdir docker_sample
cd docker_sample
接下来,准备所需文件。
$ touch Dockerfile
$ mkdir app
$ touch app/main.rb
如果目录如下所示,那就没问题。
$ find .
.
./app
./app/main.rb
./Dockerfile
在实际文件中,应按照以下方式进行描述。
FROM ruby:2.7
WORKDIR /var/www
# /var/wwwの部分は/myappなどなんでも良い
COPY ./app /var/www
执行以下命令:
$ docker image build -t sample_app:latest .
然后会显示如下内容。
[+] Building 3.3s (8/8) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 143B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ruby:2.7 3.1s
=> [internal] load build context 0.0s
=> => transferring context: 57B 0.0s
=> [1/3] FROM docker.io/library/ruby:2.7@sha256:2347de892e419c7160fc21dec721d595273 0.0s
=> CACHED [2/3] WORKDIR /var/www 0.0s
=> [3/3] COPY ./app /var/www 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:4aff41a0a11e60c78693c2d4bb5b0e00cfdbe98747c725a03666e4df 0.0s
=> => naming to docker.io/library/sample_app:latest
说明



启动Docker容器
Docker有其生命周期。

需要先创建Docker镜像,然后才能创建和启动Docker容器。
我們將嘗試確保在此次的Docker容器啟動時,app/main.rb的”Hello World!”能夠被執行。
p "Hello World!"
FROM ruby:2.7
WORKDIR /var/www
# /var/wwwの部分は/myappなどなんでも良い
COPY ./app /var/www
CMD ["ruby", "/var/www/main.rb"]
我会在docker容器启动时加入以下命令:
CMD [“ruby”, “/var/www/main.rb”]
あくまでdocker container上でコマンドを実行するためディレクトリはDockerfileで記述した/var/www内のmain.rbになっているということですね。
Dockerfileを編集したのでdocker imageを再度ビルドします。
请用中文将以下内容改写成另一种表达方式:
$ docker image build -t sample_app:latest .
用docker构建镜像,命名为 sample_app:latest,构建路径为当前目录。
ビルドが完了したらいよいよdocker containerを起動します。

run命令是创建和启动容器的命令,也适用于后续的docker-compose讨论。
$ docker container run --name sample_app_container sample_app:latest
"Hello World!"
会调用main.rb中的”Hello World!”。
要确认 Docker 容器是否已启动,请执行以下命令。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
嗯,就算我开启了它,却没有显示出任何东西呢。
由于完成了“Hello World!”的处理,该Docker容器已自动停止。
需要添加-a选项才能确认已停止的容器。
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
084abfd63748 sample_app:latest "ruby /var/www/main.…" 5 minutes ago Exited (0) 4 minutes ago sample_app_
Exitedとなっているので停止していることがわかりますね。
docker containerの説明をしたいのに我ながら例が悪かったと思いますのでファイルを修正して再度試してみましょう。
p "Hello World!"
sleep(100)
以这种方式,容器将持续运行100秒,让我们进行确认。
我会删除一个docker容器。
$ docker container rm sample_app_container
sample_app_container
重新构建Docker镜像。
$ docker image build -t sample_app:latest .
再次启动容器。
$ docker container run --name sample_app_container sample_app:latest
ここでdocker container lsを実行しようとすると…
あ、ターミナルが入力を受け付けてくれませんね。
docker containerのログが出力されるようになっているためです。
別タブを開いてもいいですが、バックグラウンドでコンテナを起動するモードがあるのでそれを試してみましょう。
docker containerコマンドを実行する際に-dオプションをつける必要があります。
$ docker container run -d --name sample_app_container sample_app:latest
0cc709282c933d71b424b0856eef0eb12d974ca4f3fb31604aeb7eec874a28d8
バックグラウンドでコンテナが起動しているか確認してみます。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0cc709282c93 sample_app:latest "ruby /var/www/main.…" 3 minutes ago Up 8 seconds sample_app_cont
可以确定启动了。
要对正在运行的容器执行命令,请按以下方式操作:
$ docker container exec sample_app_container ruby -v
ruby 2.7.8p225 (2023-03-30 revision 1f4d455848) [aarch64-linux]
通过使用”docker container exec + 容器名称 + 〇〇”的方式,您可以访问容器中的文件。
停止并删除容器。
コンテナを停止→削除するには以下の手順です。
停下来
$ docker container stop sample_app_container
sample_app_container
删除
$ docker container rm sample_app_container
sample_app_container
让我们试试使用Gem。
让我们尝试更加实际地操作一下。假设在Docker环境中使用gem。
もうお気づきの方もいるかもしれませんが先ほどの挙げたdocker container exec + コンテナ名 + 〇〇というコマンドを応用して
docker container exec bundle installなどとすればgemが利用できそうですよね。
ただ、それだとdocker containerを起動するたびにそのコマンドを実行しなければならず、そんなことやってられないですよね。
因此,在Dockerfile中进行添加。
FROM ruby:2.7
WORKDIR /var/www
# /var/wwwの部分は/myappなどなんでも良い
COPY ./app /var/www
#gemをインストールする先のパスを指定する(あまり深く考えなくていいです)
RUN bundle config --local set path 'vendor/bundle'
RUN bundle install
CMD ["ruby", "/var/www/main.rb"]
您可以使用RUN命令指定在构建Docker容器镜像时要执行的命令。
我们不能忘记创建Gemfile。这次我们以著名的nokogiri为例,确认gem是否可用。
source "https://rubygems.org"
gem 'nokogiri'
将main.rb修改为以下内容。
require 'nokogiri'
require 'open-uri'
# ウェブページを取得(今回はwikipediaを例に取ります)
doc = Nokogiri::HTML(open('https://ja.wikipedia.org/wiki/'))
# タイトルを表示
puts doc.title
让我们重新构建镜像并启动容器。

启动容器
$ docker container run --name sample_app_container sample_app:latest
/var/www/main.rb:5: warning: calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open
Wikipedia
gemを利用してWikipediaというtitleが取得できていることがわかります。
/var/www/main.rb:5: warning: calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open
という警告が出ていますがあくまでサンプルアプリなのでそこはご愛嬌でお願いします。(gemが使えることをおみせしたかっただけなのです)
docker composeとは?
我写了这么长时间,你可能会想:“在实际工作环境中何时会用到docker-compose??”
终于到了正题,接下来是docker-compose。
在实际工作中使用的应用程序。
-
- webサーバー
- データベース
など複数のアプリケーションやミドルウェアが一つになって一つのシステムが出来上がっていると思います。
(ほかにも例を挙げるならバッチ処理やフロントエンドのアプリケーションなど…)
それらのアプリケーションごとにDockerfile用意してコンテナ起動して…なんてやっていられないですよね。相互の連携まで考えたら頭が痛くなります。
在这里就需要使用docker-compose。
让我们试着实际使用Docker Compose。
ここからはrailsを題材にwebアプリケーションをdocker環境で構築できるようになってみたいと思います。
別のディレクトリを用意していただいた方がわかりやすいと思うので僕は今回はdocker_rails_sampleというディレクトリを用意しました。以下のファイルを用意してください。
FROM ruby:2.7
WORKDIR /var/www
COPY ./app /var/www
RUN bundle config --local set path 'vendor/bundle'
RUN bundle install
Dockerfile现在不需要解释了吧。
source "https://rubygems.org"
gem 'rails'
version: '3'
services:
db:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./app/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./app:/var/www
ports:
- "3000:3000"
environment:
RAILS_ENV: development
depends_on:
- db
讲解

执行rails new


由于这些更改,我们需要重新构建Dockerfile和Gemfile中的内容,就像往常一样。
构建 Docker Compose 镜像。
# (中略)
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
# ↓ここに先ほどdocker-compose.ymlファイルで指定したMYSQL_ROOT_PASSWORDの値を入
password: password
# ↓ここに先ほどdocker-compose.ymlファイルで指定したdbというコンテナ名を指定
host: db
# (中略)

已成功创建了数据库。
いよいよです。
$ docker-compose up
试试访问下面的网址
http://localhost:3000/

成功了〜〜
结束
どうでしょう。ここまでくれば実務で見かけるDokcerfileやdocker-compose.ymlファイルをみて「あ!これってこういうことしてるんだ!」と今までわからなかったことがわかるようになっているのではないでしょうか。
僕自身前までは「なんだかいろいろやってんだな…」くらいの理解で自分の中で完全にブラックボックス化していましたが、今回腰据えて一から勉強してみて非常に有意義だったのでぜひ駆け出し・新卒エンジニアの皆さんは僕のように4年も放置せずキャッチアップしてもらいたいです。
非常感谢您阅读到最后。
文献引用