April 26, 2020
今更だけどDockerコンテナ技術の理解が曖昧だったのでコンテナ再入門
昨今のシステム開発では、コンテナの技術が欠かせない。
しかし今まで他人のDockerfileを拝借していたので、私の理解は曖昧だった。
既存ファイルを流用することも大切だが、Dockerのバージョンアップで急に動かなくなったり、設定の誤りでエラーが出たりと、基礎を知らない人は環境構築で挫折することが多い。
最低限の基礎を理解するため、こちらの本を読んでみた。
Dockerの基本、docker-composeによるRails環境を構築するハンズオンを試してみた。
Dockerfileの書き方
まず Dockerイメージをビルドする とは、コンテナの元になるイメージを作ることをさす。
# Dockerfile
FROM golang:1.9
RUN mkdir /echo
COPY main.go /echo
CMD ["go", "run", "/echo/main.go"]
FROM では、Dockerイメージのベースとなるイメージを指定し、ビルド時に指定されたイメージがダウンロードされる(取得イメージはデフォルトでDocker Hubレジストリを参照)
RUN では、コンテナで実行するコマンドを定義でき、引数はコマンドをそのまま指定できる。
COPY では、ホストマシンにあるファイル等をコンテナにコピーする操作となる。
CMD では、コンテナで実行するプロセスを指定できる(RUNではアプリケーションの更新や配置、CMDでアプリケーションそのものを動作させる)
コンテナの操作
サンプル作成したコンテナ環境で、main.goの動作確認を行う。
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
log.Println("received request")
fmt.Fprintf(w, "Hello Docker!!")
})
log.Println("start server")
server := &http.Server{Addr: ":8080"}
if err := server.ListenAndServe(); err != nil {
log.Println(err)
}
}
まずイメージを作成し、コンテナを実行する(-dでバックグラウンド、-pでポートフォワーディング)
docker image build -t example/echo:latest .
docker image ls
docker container run -d -p 9000:8080 example/echo:latest
docker container ps
localhost:9000で「Hello Docker!!」が表示されたら、不要なコンテナとイメージを削除する。
docker container stop コンテナID
docker container rm コンテナID
docker image ls
docker rmi イメージID
イメージの操作
Dockerイメージ は、Dockerコンテナを作成するためのテンプレートで、OSとして構成されたファイルシステム、コンテナ上で実行するためのアプリケーション、設定情報などが含まれている。
イメージの操作 に関連するコマンドは次のとおり↓
# イメージのビルド
## -t オプションで[イメージ名]と[タグ名]を指定.
docker image build -t イメージ名:タグ名 Dockerfile配置ディレクトリのパス
## -f オプションは、指定ファイル(Dockerfileでない名称)を指定してイメージをビルド.
docker image build -f Dockerfile-test -t example/echo:latest
## --pull オプションは、ベースイメージを強制的に再取得してイメージのビルド.
docker image build --pull=true -t example/echo:latest
# イメージの取得
## DockerレジストリからDockerイメージをダウンロード.
docker image pull [options] リポジトリ名:タグ名
## 例) jenkinsのイメージ取得コマンド.
docker image pull jenkins:latest
# イメージの削除
## 削除
docker rmi イメージID
## 強制的に削除.
docker rmi -f イメージID
# イメージの一覧
## Dockerホストに保持されているイメージの一覧表示.
docker image ls [options] [リポジトリ:タグ]
# イメージのタグ付け
## Dockerイメージのタグはある特定のイメージIDを持つDockerイメージを識別しやすくするために利用.
docker image tag 元イメージ:タグ 新イメージ:タグ
コンテナの操作
Dockerコンテナ は 実行中・停止・破棄 の3つのいずれかに分類される。
コンテナの操作 に関連するコマンドは次のとおり↓
# コンテナの作成と実行
## Dockerイメージからコンテナを作成、実行するコマンド.
docker container run [options] イメージ名:タグ コマンド コマンド引数
docker container run [options] イメージID コマンド コマンド引数
## -p ポートフォワーディング(ホスト側の9000ポートからコンテナ側の8080ポートへアクセス)
## -d バックグラウンド
docker container run -d -p 9000:8080 example/echo:latest
## 名前付きコンテナ
docker container run --name コンテナ名 イメージ名:タグ
docker container run -t -d --name gihyo-echo example/echo:latest
# コンテナの一覧確認
## 実行中のコンテナ及び終了したコンテナの一覧表示.
docker container ls [options]
## 例) コンテナIDのみ抽出.
docker container ls -q
## 例) 特定のコンテナ名のみ抽出.
docker container ls --filter "name=echo1"
## 例) 特定のイメージで抽出.
docker container ls --filter "ancestor=example/echo"
## 例) 終了したコンテナも抽出.
docker container ls -a
# コンテナの停止
## 実行中のコンテナの停止.
docker container stop コンテナID または コンテナ名
# コンテナの再起動
## 一度停止したコンテナの再実行.
docker container restart コンテナID または コンテナ名
# コンテナの破棄
## 停止したコンテナの完全廃棄.
docker container rm コンテナID または コンテナ名
## 実行中のコンテナを強制的に破棄.
docker container rm -f コンテナID または コンテナ名
# 実行中のコンテナ操作
## 実行中コンテナの中で任意のコマンドを実行.
docker container exec [options] コンテナID または コンテナ名 コマンド
docker container exec -it cronjob tail -f /var/log/cron.log
運用向けの操作
コンテナの一括削除 に関連するコマンドは次のとおり↓
# 実行していないコンテナの一括削除.
docker container prune [options]
# 不要なイメージファイルの一括削除.
docker image prune [options]
# コンテナ、イメージ、ボリューム、ネットワークなどDockerリソースを一括削除.
docker system prune
Docker-Composeの基本
システム開発ではアプリケーションの連携が必要になり、docker-composeが一般的になる。
docker-compose は、yaml形式で定義された設定ファイルで複数のコンテナ実行を一括管理する。
version: "3"
services:
echo: # コンテナ名
image: example/echo:latest # Dockerイメージ
ports: # ポートフォワーディング(ホスト/コンテナ)
- 9000:8080
docker-composeの基本コマンドは次のとおり↓
# イメージのビルド
docker-compose build
# コンテナ群の起動(--buildは必ずビルド実施)
docker-compose up -d
docker-compose up -d --build
# コンテナ群の停止(--rmiはイメージも併せて削除)
docker-compose down
docker-compose down --rmi all
# プロセスの確認
docker-compose ps
永続化データの取扱い
コンテナ実行中に書き込まれたファイルは、ホストにマウントしない限り、コンテナ破棄のタイミングで消去されるため、ステートフルな運用を実現するために Data Volume を利用する。
# docker container run [options] -v ホスト側のpath:コンテナ側のpath リポジトリ名:タグ名 コマンド 引数
docker container run -v ${PWD}:/workspace ghyodocker/imagemagick:latest convert -size 100*100 xc:#000000 /workspace/gihyo.jpg
チュートリアル(Rails)
最後にdocker-compose上でRails開発環境を構築していく。
まずカレントディレクトリ配下のrorディレクトリにDockerfileを作成する。
FROM ruby:2.4.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
Gemfileを作成(併せて空ファイルのGemfile.lockも作成)
source 'https://rubygems.org'
gem 'rails', '5.0.0.1'
docker-compose.ymlを次のように定義する。
# 参考文献(https://discuss.circleci.com/t/postgres-just-stopped-working/34511/4)
version: '3'
services:
db:
image: postgres
environment:
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
事前にFile Sharingでカレントディレクトリを追加する。
docker-compose run web rails new . --force --database=postgresql
Gemfileを一部修正。
# 修正前)
gem 'pg', '~> 0.18'
# 修正後)
gem 'pg', '~> 0.20.0'
修正分を含めるために再度ビルドを実行。
docker-compose build
データベース設定(config/database.yml)の追加。
# 修正前)
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
# 修正後)
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
動作検証のコマンドは次のとおり↓
# 起動
docker-compose up -d
# データベース作成.
docker-compose run web rake db:create
# アクセス.
http://localhost:3000/
# コンテナ群の停止.
docker-compose down