LoginSignup
294
431

Dockerの"分からない"を簡単にメモ

Last updated at Posted at 2023-07-27

概要

Dockerの勉強を始めてから入門的なことはできるけど、仕組みが完全に理解できていない。なんて自分向けにノートを書きました。

同じように困ってる人が一人でもいるのであれば解決してあげたい。

前提

  • 大前提としてDockerのOSはLinuxベースであること

    • MACやWindowsのようなGUI操作ではない
    • ディストリビューションはレイヤーの一部
  • まずはレイヤーの仕組みを知っておこう

  • Dockerイメージを作成するときにDockerfileに記述された手順に沿って、1つのイメージを作成することになる

    • この時に作成されたイメージはレイヤ構造と呼ばれ、1つの手順は1つのレイヤーに該当する
    • RUNCMDが増えれば増えるほどレイヤーの数が増える

規約

  • レイヤーを理解したうえでDockerには規約と推奨が存在することに留意

  • 規約

    • コンテナはエフェメラルであること
    • .dockerignoreを有効活用する
    • 不要なパッケージのインストールを避ける
    • コンテナ毎に1つのプロセスだけ実行
    • レイヤーの数を最小に
    • 複数行の引数はアルファベット順、改行すること

コンテナはエフェメラル(短命:ephemeral)であること

最小のセットアップで生成・停止・破棄が可能であること

.dockerignoreを有効活用する

.gitignoreみたいに特定のファイル指定をすることで、イメージ作成時、Dockerfileの特定のファイルを除外することができる

> ignoreを作成する例

# ここで指定されたファイルを例外として登録されます
.temp

不要なパッケージのインストールを避ける

複雑さ、依存関係、ファイルサイズ、レイヤー数を減らすために、余分なパッケージはインストールを避ける。

例)データベースイメージにテキストエディタ系のファイルは不要

コンテナ毎に1つのプロセスだけ実行

(特殊な場合を除いて)1つのコンテナの中で1つのプロセスだけの実行にする

複数のコンテナに分けることで、再利用や水平スケールが可能となる

レイヤーの数を最小に

Dockerfileの可読性を下げないために、使用するイメージやレイヤーは最小化しておくこと

複数行の引数はアルファベット順、改行すること

(可能であれば)複数行の引数をアルファベット順、改行すること

Dockerfile
# buidpack-depsの記述する際の例
RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion

Docker network

概要

コンテナは作られた時は独立した存在として確立される(完全分離:isolation

ただし、コンテナ毎に1つのプロセスを実行する関係上、追加の機能や実装にはコンテナ間の連携が必要になる

そこでDocker networkを利用して、コンテナ間通信を行う

ネットワークはすべてユーザ定義ネットワークと呼ばれ、作成や変更を任意に行うことができる


  • Dockerはインストールされたときに自動的に3つのネットワークを作成する(デフォルトネットワーク:Default Networks)
    • デフォルトネットワークは削除されない
  1. bridge
  2. none
  3. host

bridge

bridge

コンテナ起動時にネットワークを指定しなければ自動的にこれに割り当てられる

Linuxのブリッジ機能を使った通信方法で、コンテナ外まで通信する場合はルーティング機能が使われる

コンテナ内での連携通信など基本はこれ

none

none

ネットワークの接続が必要ないコンテナを作成する場合に使われるドライバ

設定されると固有のインタフェース名が作られる

host

host

作成すると操作しているホストマシンと同じネットワークにするドライバ

作成した瞬間にDockerホストマシンと同じネットワークインタフェース、IPアドレスを持つようになる!


それ以外にもユーザーが独自に定義できるネットワークが3つ存在する

  1. overlay
  2. ipvlan
  3. macvlan

overlay

overlay

複数のDockerコンテナと接続し、ホストとのルーティングを初めからなくすことができる

本来brigeとhostのコンテナを繋ぐためにはホストマシンとのルーティングが必要

ipvlan

接続時IPv4とIPv6の両方のアドレスを指定し、任意の数値にすることができる

主にポートフォワーディングとかに使う?(扱ったことがない)

macvlan

macvlan

コンテナにMACアドレス(物理固有アドレス)を設定し、コンテナをネットワーク上の物理デバイスとして表示することができる。

物理ネットワークに直接接続されることが想定された古いアプリケーションを扱う場合などに使われる

Docker Volume

概要

コンテナで生成され利用するデータは、コンテナ間でのやり取りは出来ず、一度削除したら消え、ホストからは操作できないものである

しかし、Docker Volumeを扱うことによってコンテナ間利用されるデータをマウント、永続的に保持することができる

コンテナ外のストレージを利用する機能の総称をDocker Volumeと呼ぶ


  • Docker Volumeは共通で以下のような特徴がある

    • Docekr CLIコマンドやDocker APIを使って管理することができる
    • LinuxとWindows上のコンテナで動作する
    • 複数のコンテナ間で安全に共有することができる
    • Volumeを新たに生成すると、その内容はコンテナがあらかじめ用意していた内容になる
  • 外部ストレージにマウントする手法として3種類存在する

    1. bind mount
    2. volume(匿名ボリューム,名前付きボリューム)
    3. tmpfs mount

bind mountvolumeはホストのファイルシステム上に作成されるが、tmpfs mountはメモリ領域に作成される点に注意!

volume

bind mount

ホスト側のディレクトリをコンテナ内のディレクトリと共有する

ほかのプロセスに干渉される可能性がある

volume

Dockerの管理の元、ストレージ領域を確保する

コンテナ内での変更がホストマシンに影響しないため、基本はこれを使うこと

  • 匿名ボリュームと名前付きボリュームが存在する
    • 匿名ボリューム
      • 作成する際に名前を作らず、任意のハッシュ値を名前として扱う
      • コンテナ停止と共に自動的に削除される
    • 名前付きボリューム
      • 作成する際に名前とタグを設定する。
      • -rmオプションを使うことでコンテナ停止と共に自動的に削除される

tmpfs mount

メモリ上にストレージを確保する。

  • 基本的には一時的に避難されるような状況で使われる。
    • ホストまたはコンテナーの書き込み可能レイヤーに保持したくない機密ファイルを一時的に保存する場合など

Docker Volumeを利用するには2つのオプションが存在する

-v
--mount
  • 利用するときは基本どちらでもおk(公式は-mountを推奨している)
    • -v-mountは同じ書き方ではない点に注意
    • 一部のオプションを利用したい時は-mountを利用する必要あり

Dockerfileを扱う

コンテナを生成するためにはDockerfileと呼ばれるファイルを編集する必要がある

既存のイメージなどに追加でレイヤーを入れることでより多機能のコンテナの作成が可能!

まずはDockerfileを作成する!

任意のディレクトリでDockerfile(拡張子なし)を作成

Dockerfileの作成

FROM:ベースイメージを作成

最初にベースとなるイメージを指定し、ここからコマンドを組み立てていく!

FROM centos:centos7
  • ここで指定するディストリビューションでそのあとのコマンドが変わってくるため注意!
    • ununtu > apt update
    • centOS > yum update

RUN: 任意のコマンドを実行する

Linuxコマンドを実行し、レイヤーを追加していく!

vimを追加するには以下のような記述を行う

RUN yum install -y vim

また、Javaをインストールしたい場合は、 公式サイトからJavaのリンク を参照する

公式サイトリンク

RUN yum -y install https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.rpm

WORKDIR: ワークディレクトリを追加する

操作するディレクトリの絶対パス(推奨)を指定する!

以降はそのディレクトリを基準にDockerfileに書いた操作が実行される。

WORKDIR /usr/src
  • このコマンドでは存在しないパスを指定した場合は新規で作成される
    • ディレクトリを作成するためには使わない

レイヤーの確認

Dockerfile
FROM centos:centos7
RUN yum install -y vim https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.rpm

WORKDIR /usr/src

コンテナの生成と停止

imageを作成

docker image buildを入力することイメージを作成できる!

Dockerfileがある場所で

docker image build --tag docker-java:app  .
  • tag > コンテナの名前とタグを設定する

ビルドしたらdocker imagesで実際に作られたか確認すること!

runでコンテナを起動

docker container runでコンテナ生成と起動を同時に行うことができる

docker container run -itd -v ${PWD}/src:/var/src docker-java:app 
  • itd > 一度コンテナを起動したらそのままにする
  • v > バインドマウントでDockerを同期

stopでコンテナを停止

docker container stopでコンテナを停止させることが可能

docker container stop docker-java:app 

pruneでDockerのお掃除

ビルド、イメージの作成を行っているとキャッシュが溜まるので適宜、クリアしておくこと

# 停止しているコンテナ、ネットワーク、ボリュームの削除
docker system prune 

# イメージの一括削除
docker image prune 

Docker Compose

複数コンテナを同時に起動したいけど、毎回コンテナを起動するときにdocker container runするのは大変・・・

そこで、Docker Composeを利用することで一回のコマンドで複数コンテナの起動、bridgeネットワークに接続が可能!

Docker Composeとは

手っ取り早く、コンテナの起動を楽にするツールであり、イメージを作るツールではないこと!

既存のDockerfileに+compose.yml(旧docker-compose.yml)を使うことによって、複数の生成が可能になる

compose.yml の作成

compose.yml(旧docker-compose.yml)を以下のような感じで記入する(一例)

compose.yml
# バージョンの指定(現在はバージョン指定が推奨されていない!)
# version: '3.9'

# 大まかに作ったものを流していく工程
services:

# 1つ目のコンテナ
  db:
# Dockerfileの指定
    build: docker/postgresql

# 接続ポートの選択
    ports:
      - 5432:5432

# 環境変数の指定
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: root

# bind mountの指定
    volumes: [ ./data:/var/lib/postgresql/data ]

# 2つ目のコンテナ
  java:

# Dockerfileの指定
    build: docker/java

# 接続ポートの選択
    ports:
      - 9080:9080

# 一度起動したら、そのままにする
    tty: true

# bind mountの指定
    volumes: [ ./src:/usr/src:cached ]

書き込みが完了したらdocker-composeコマンドでビルドができる

# ビルドする例
docker-compose up -d

networkの秘密

  • Docker composeは同時に立てた時に自動的にbrigeネットワークを繋いでくれる

  • そのため、立てる際にネットワークオプションを省いても接続が可能になる

  • しかし、デフォルトネームで固定されるため、別途ネットワークオプションを使いたいときはdocker-compose.ymlにnetworkオプションを追記すること

猿でもできるコンテナデータベース

compose.ymlでファイルを作成

compose.yml
services:

  # データベースイメージ(MySQL)
  db:
    image: mysql:8.0.21 
    command: --default-authentication-plugin=mysql_native_password

    restart: always

    #ログイン情報
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: hoge 
      MYSQL_USER: hoge     
      MYSQL_PASSWORD: hoge

    #データベース接続ポート
    ports:                 
      - 3306:3306          

  # 管理者ログインイメージ
  adminer:
    image: adminer:latest
    restart: always
    ports:
      - 8080:8080

docker compose up -dでコンテナをたてれば完了

下記リンクに接続するだけでデータベース編集画面に直行
http://localhost:8080/

編集画面

devcontainer

VSCodeの拡張機能でdevcontainerと呼ばれるツールがある

  • 機能の役割としては

    • Docker composeをコンテナを開いた際に自動的に実行してくれる
    • 構成ファイルをdocker-compose.ymlから読み込むことができる
    • 拡張機能をコンテナを開く際に選択できる?
  • こいつ単体だとコンテナのシステム掃除(prune)ができないため、裏でWSLを起動して適宜運用するのがいい?

294
431
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
294
431