LinuxでDocker¶
コンテナの設定¶
コンテナの粒度¶
1つのコンテナでいくつものプロセスを稼動させるか、1つのコンテナで1つのプロセスを起動させるか、について。
- sshdを入れてbashで外部から接続してあたかも独立したノードと見せることもできそうだが、それなら仮想マシンの方がよいと思う
- Redmine(Nginx + Unicorn + MySQL)をDockerで動かすとしたら
- 構成1) 3つのコンテナを立て、それぞれでNginx、Unicorn、MySQLを個別に稼動
- 構成2) 1つのコンテナを立て、その中でNginx、Unicorn、MySQLを一緒に稼動
- 構成3) 2つのコンテナを立て、1つでNginx、Unicornを、もう1つでMySQLを稼動
- 構成4) 2つのコンテナを立て、1つでNginxを、もう1つでUnicorn、MySQLを稼動
どれがよいだろう?
Dockerは、アプリケーション単位のコンテナなので、1つのコンテナで1つのプロセスを動かすのが基本。
複数のアプリケーションをまとめて動かすのであれば、Linuxコンテナ(LXC)が向いているようだ。
ケーススタディ1)GrafanaとInfluxDB¶
主に時系列データを可視化するGrafanaと、時系列データに特化したデータベースInfluxDBと2つのアプリケーションを組み合わせたシステムをDockerで実行します。
Dockerでは、アプリケーション毎に1つのコンテナで動かすのが基本なので、GrafanaのコンテナとInfluxDBのコンテナの2つコンテナを使用します。
また、Dockerは停止するとファイルシステムが
コンテナホストのファイアウォールとコンテナのポート¶
コンテナホストのファイアウォールでは閉じている(遮断している)ポートを指定してDockerアプリケーションを起動したところ、外部からそのポートへアクセスができてしまう。
これは、Dockerの実行に指定したポートはInboundではなく、仮想ネットワークへ転送される(NAT)仕組みのため、Linuxのファイアウォール設定で閉じていても通信できてしまう。
Rocky Linux 8でDockerの場合¶
Dockerをインストールしたところ、/etc/firewalld/zones/docker.xmlが生成されていた。
<?xml version="1.0" encoding="utf-8"?>
<zone version="1.0" target="ACCEPT">
<short>docker</short>
<description>zone for docker bridge network interfaces</description>
</zone>
publicゾーンとは別にdockerゾーンが生成されている
~$ firewall-cmd --get-active-zones docker interfaces: docker0 public interfaces: eth0 ~$
ネットワーク¶
同じサーバー上で動く別コンテナへのアクセス¶
同じサーバー上であっても異なるコンテナで動作するサービスへは localhost では接続できません。
永続化¶
Docker コンテナは、イメージからコンテナを生成後、start/stop をしている限りはコンテナ内に作成したファイルは保持されます。しかし、コンテナを破棄して再度イメージからコンテナを生成すると、コンテナ実行中に変更したストレージデータは消えてしまいます。
イメージを更新した場合(例:バージョンアップ)も、コンテナは新たに生成されるので、前のコンテナのストレージデータは引き継ぎできません。
そこで、永続化したいアプリケーションのデータはコンテナの外部に置く必要があります。
永続化の手段¶
- volume
- bind mount
volumeは、dockerが管理する領域の中に永続化データのボリュームを設け、コンテナからそのボリュームをマウントして使用します。
bind mountは、ホストOSの特定ディレクトリをコンテナ内のディレクトリパスにmountして使用します。
ボリューム¶
- ボリュームの作成
docker volume create myvolume
コンテナの管理¶
コマンド¶
旧コマンド¶
コマンド | 内容 | 備考 |
docker run | イメージを取得してコンテナを生成し、コンテナを実行 | |
docker ps | コンテナの一覧 | -a オプションで全てのコンテナを表示(デフォルトは起動中のコンテナ) |
docker start | 作成されたコンテナを実行 | |
docker stop | 実行中のコンテナを停止 | |
docker rm | コンテナを削除 | |
docker image ls | ローカルに格納済みのコンテナイメージの一覧 | |
docker pull | Docker Hub(公式リポジトリ)から既存のイメージをダウンロード | |
docker rmi | イメージの削除 |
新コマンド¶
Docker v1.13以降で使用します。以下はコマンドの抜粋です。
コマンド | 内容 | 備考 | |
---|---|---|---|
docker container run | 新しいコンテナでコマンドを実行 | ||
docker container start | 停止しているコンテナを起動 | ||
docker container stop | 実行中のコンテナを停止 | ||
docker container create | 新しいコンテナの作成 | ||
docker container rm | コンテナの削除 | ||
docker container ls | コンテナの一覧 | -a オプションで全てのコンテナを表示(デフォルトは実行中のコンテナ) |
|
docker container attach | 実行中のコンテナにローカルの標準入出力を接続 | ||
docker container exec | 実行中のコンテナ上でコマンド実行 | ||
docker container stats | 実行中のコンテナの使用リソースを表示(CPU/Mem/Net/IO) |
docker container top | コンテナ上で実行されているプロセス一覧 |
docker image build | Dockerfileからコンテナイメージを構築 | ||
docker image pull | レジストリからイメージを取得 | ||
docker image ls | イメージの一覧 | ||
docker image rm | イメージを削除 | ||
docker system df | dockerの使用ディスク容量を表示 | ||
docker system prune | 未使用のオブジェクト(コンテナ、イメージ)を削除 | ||
docker volume ls | ボリュームの一覧 | ||
docker volume create | ボリュームの作成 | ||
docker volume rm | ボリュームの削除 | ||
docker volume prune | 未使用のボリュームをすべて削除 |
docker container run¶
runは、コンテナのイメージを公式リポジトリから取得し、コンテナを作成し、コンテナを実行します。
実際には、pullコマンド、createコマンド、runコマンドを一気に実行するのがrunコマンドになります。
書式
docker container run [オプション] IMAGE [COMMAND] [ARGS...]
オプション(抜粋)
- --detach, -d バックグラウンドでコンテナを実行しIDを表示
- --interactive, -i アタッチせずとも標準入力を開く
- --tty, -t 擬似TTYを割り当て
- --env, -e 環境変数を指定
- --publish, -p コンテナのポートをホストに公開
- --name コンテナ名を付与。省略するとランダムな名前(科学者、ソフトウェアの著名人に基づくランダムな氏名)が付与
例
~$ sudo docker container run -d --name redmine-trial -p 3000:3000 redmine:6.0.3 Unable to find image 'redmine:6.0.3' locally 6.0.3: Pulling from library/redmine Digest: sha256:cdbf1b0081787842e3e3138f90a1c2df0fbcb81e93a84aa4d4611719741c0ac8 Status: Downloaded newer image for redmine:6.0.3 5d68c8b28aa3deadb2c8497eac3f788878b880ebd0a9fe3722e965aabd735d29
- ローカルにイメージが存在しないので、dockerリポジトリよりイメージをダウンロードして実行
一度runコマンドを実行して生成したコンテナが停止したとき、コンテナを再実行するには、すでにコンテナが作成済みとなっているのでrunコマンドではなくstartコマンドを使います。
docker container attach¶
attachは、実行中のコンテナのプロセス(PID=1)を、attach実行ターミナルの標準入力、標準出力、標準エラーに接続します。
docker container exec¶
execは、実行中のコンテナ上で指定したコマンドを実行します。
よく行われるのは、コンテナ上でbashを実行し、そのbashでshell環境の操作をすることです。その場合、-it
オプション指定します。
~$ docker container exec -it mycontainer bash
dockerコマンドの実行でsudoを不要に¶
sudoでroot権限にならなくてもdockerコマンドを実行できるように、dockerグループにユーザーを追加します。usermod -aG docker tom
docker compose¶
複数のプロセスが連携するアプリケーションをDockerで動かす場合、それぞれのプロセスをDockerで起動する必要があります。
docker composeは、この複数のコンテナの組み合わせを管理するコマンドです。
docker compose up¶
docker-compose.ymlを定義し、そのディレクトリでこのコマンドを実行すると、docker-compose.ymlに定義したコンテナを生成し、実行します。
docker compose down¶
docker-compose.ymlのあるディレクトリでこのコマンドを実行すると、docker-compose.ymlに定義したコンテナを停止・破棄します。
すなわち、stopとrmを実行します。
docker compose stop¶
docker-compose.ymlのあるディレクトリでこのコマンドを実行すると、docker-compose.ymlに定義したコンテナを停止します。
docker compose start¶
docker-compose.ymlのあるディレクトリでこのコマンドを実行すると、docker-compose.ymlに定義したコンテナを開始します。
コンテナのイメージ¶
コンテナを実行するには、コンテナイメージが必要となる。イメージは外部から取得するか自分で作成するかとなる。
主要なアプリケーションはコンテナイメージが提要されている。
コンテナの状態¶
状態名 | 内容 |
---|---|
created | |
running | |
paused | |
exited |
手順¶
Grafana¶
InfluxDB と Grafana を双方 Docker 上で実行します。
docker composeで実行¶
InfluxDBとGrafanaの2つのDockerコンテナを生成・実行するとき、docker composeを用いると簡単に実行できます。
docker-compose.ymlの作成¶
docker composeでは、実行するコンテナ群の定義を docker-compose.yml ファイルに記述します。
version: "3"
services:
influxdb:
image: influxdb
container_name: influxdb
restart: always
volumes:
- ./influxdb:/var/lib/influxdb2
ports:
- 8086:8086
- 8083:8083
environment:
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: myname
DOCKER_INFLUXDB_INIT_PASSWORD: mypassword
DOCKER_INFLUXDB_INIT_ORG: myorg
DOCKER_INFLUXDB_INIT_BUCKET: mybucket
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: my_secret_token
grafana:
image: grafana/grafana
container_name: grafana
user: "root"
restart: always
volumes:
- ./grafana:/var/lib/grafana
depends_on:
- influxdb
ports:
- 3000:3000
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- InfluxDBのアカウント、パスワード、APIトークンなどを記述できます。
- パスワードは文字数の規定あり(5文字では起動時にエラー)
- Grafanaのパスワードは初回接続時に変更を促された
イメージの作成¶
Ubuntuユーザーランドのイメージ作成¶
まず、作業ディレクトリを作成し、Dockerfileを記述します。
work$ mkdir hello-ubuntu work$ cd hello-ubuntu hello-ubuntu$ vi Dockerfile
Dockerfileを作成します。ここでは、ubuntuイメージの最新を取得し、apt update で最新化、apt installで追加パッケージをインストールします。
FROM ubuntu:latest RUN apt update -y && apt install -y iputils-ping net-tools curl
イメージを作成します。
hello-ubuntu$ docker image build -t test-image:v1 .
イメージが生成されたことを確認
hello-ubuntu$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE test-image v1 82e007336365 36 minutes ago 121MB ubuntu latest 58db3edaf2be 2 weeks ago 77.8MB
イメージからコンテナを生成し実行します。
hello-ubuntu$ docker run --name test-container1 -it test-image:v1 /bin/bash
- -it オプションを指定し、標準入力とターミナルを使用
rubyのhello¶
コンテナイメージの作成¶
Rubyで動くアプリケーションをDockerコンテナとして作成します。
作業ディレクトリを作成し、その中に Dockerfile
の名前でDockerイメージの定義を記載します。
docker$ mkdir hello_ruby
docker$ cd hello_ruby
hello_ruby$ vi Dockerfile
- Dockerfile
# syntax=docker/dockerfile:1 FROM ruby:3.3.7-slim COPY src/hello.rb . CMD ["ruby", "hello.rb"]
Dockerアプリケーションのランタイム(今回はruby)をベースイメージとします。docker公式リポジトリにある、ruby 3.3系の最新版(3.3.7)のサイズ削減版(slim)を指定します。
hello.rbは、とりあえず root(トップ)ディレクトリに置きます。
- hello.rb
puts "Hello, Ruby Docker World!"
Dockerイメージを生成します。
hello_ruby$ docker image build -t hello-ruby:0.1 .
:
- -tオプションで、Dockerイメージの <リポジトリ名>:<タグ> を指定します。
生成されたイメージはローカルマシンのDocker領域に置かれるので、管理コマンドで確認します。
hello_ruby$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-ruby 0.1 e81943adfb03 13 minutes ago 150MBREPOSITORY TAG IMAGE ID CREATED SIZE
コンテナの作成・実行¶
コンテナを作成し、起動します。
hello_ruby$ docker container run --name hello_ruby hello-ruby:0.1
Hello, Ruby Docker World!
hello_ruby$
- docker container runコマンドは、コンテナをイメージから作成し、それを起動します。
~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57fcee1932be hello-ruby:0.1 "ruby hello.rb" 43 seconds ago Exited (0) 42 seconds ago hello_ruby
一度作成したコンテナが停止後、再度実行するときは docker container run
ではなく、 docker container start
コマンドを使用します。
~$ docker container start -a hello_ruby
Hello, Ruby Docker World!
~$
- -aオプションを指定しないと、デフォルトのコマンドが実行されません。
メモ¶
困ったこととその解決¶
すぐに実行が終わるコンテナにインタラクティブに接続¶
コンテナ起動後、コンテナ内でコマンドがすぐに終了してしまう場合、attachやexecで接続することができません。
その場合、一度コンテナを破棄し、docker container run -itオプション付きでコンテナを生成・実行します。
参考資料¶
Linux女子部「Docker勉強会」資料(2014-06-19 講師: 中井悦司 氏)¶