プロジェクト

全般

プロフィール

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 image build Dockerfileからコンテナイメージを構築
docker image pull レジストリからイメージを取得
docker image ls イメージの一覧
docker image rmi イメージを削除
docker volume ls ボリュームの一覧
docker volume create ボリュームの作成
docker volume rm ボリュームの削除
docker container run

runは、コンテナのイメージを公式リポジトリから取得し、コンテナを作成し、コンテナを実行します。

書式

docker container run [オプション] IMAGE [COMMAND] [ARGS...]

docker container attach

attachは、実行中のコンテナのプロセス(PID=1)を、attach実行ターミナルの標準入力、標準出力、標準エラーに接続します。

docker container exec

execは、実行中のコンテナ上で指定したコマンドを実行します。
よく行われるのは、コンテナ上でbashを実行し、そのbashでshell環境の操作をすることです。その場合、-it オプション指定します。

~$ docker container exec -it mycontainer bash

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 オプションを指定し、標準入力とターミナルを使用

参考資料

雑多

Linux女子部「Docker勉強会」資料(2014-06-19 講師: 中井悦司 氏)


約1年前に更新