LoginSignup
6
5

Docker幼稚園

Last updated at Posted at 2023-07-13

新しい端末を買うたびにDockerを導入しようとして、毎回苦戦する赤ちゃんなので、Docker幼稚園に入ります。

Dockerコンテナって?

Docker Desktopを開くとこんな感じ。
Docker Desktop Top
この左の

  • Container
  • Images
  • Volumes

の関係をまずまとめる。

Container
仮想の動作環境(=ひとつのサーバーみたいな感じ)。
例えばPCのローカル環境にpython2とpython3を同居させてると、パッケージのインストールや動作時にどっちで動かしてるんだ…?ってなるときがある。
このようにひとつの動作環境にいろいろソフトウェアを入れていく(=環境が汚れる)と、お互いが思いもよらぬ形で影響してトラブる可能性がある。
そこで仮想の動作環境(=Container)を作り、それぞれ独立させてやることで無用なトラブルを防止することができる。
Image
Containerの設計図、雛形。
これを共有することで、誰もが同じ仮想環境を構築することができる。
OSの違いや種々のライブラリの導入状況の違いを無視し、環境構築をすっ飛ばしてメインの開発から着手できるのはとてもメリット。
そしてこのImageの共有プラットフォームがDocker Hub。
Volume
複数のコンテナが共有できるデータ領域みたいなもの(まだ使っていないので曖昧)。
後述する各ContainerがマウントするVolumeとは別なのでそこだけ注意。

Containerは使い捨ての環境。
都度、作ったり消したり、起動したり停止したりするもの。
Imageはあくまで設計図なので、そのなかで作業したりはしない、ということだけまず理解する。
Image, Container, Volume

Dockerイメージってどこからくるの?

Imageは、Dockerfileというファイルをもとに作られる。
公式Dockerfileリファレンスに記載のサンプルを見てみよう。

Dockerfile
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

ひとつひとつ紐解いていく。
FROM句はDockerfileには必須の要素で、これから作るImageのベースとなるImageを指定している。
":"以降はTagと呼ばれ、Imageのバージョンのようなもの。

Dockerfile
# FROM <Image名>:<Tag>
FROM ubuntu:18.04

“ubuntu”はDocker Official Imageとして配布されているImage。
Docker Hub

このubuntu ImageからContainerを作成すると、まっさらなubuntuの環境が作成される。
その環境をもとにして、少しカスタマイズしたImageを誰かが作る。
それをもとに、また別の誰かが少しカスタマイズしたImageを作る。
このようにImageが数珠つなぎになっているというアイデアは、まさしく「巨人の肩に乗る」発想だと思った。
Dockerfile

実際、Docker Desktopで”node” Imageを見てみると、”debian” Imageを出発点として、計4つのImageの上に”node” Imageが成り立っていることが分かる。
Image Hierarchy


余談

ちなみに本当に空っぽの状態からImageを作成したい場合は、次のように指定する。

Dockerfile
# 特定のImageを指定せず、
# まっさらな状態からImageを作成する
FROM scratch

残りのコマンドは簡単なので、一気に。

Dockerfile
# カレントディレクトリの中身を、コンテナ内の/appディレクトリにコピー
COPY . /app
# コンテナ内で、/appに対してmakeコマンドを実行
RUN make /app
# コンテナ内の/app/app.pyを実行
CMD python /app/app.py

パッと見、RUNとCMDってどちらもシェル形式でコマンド実行しているだけで、何が違うの?ってなると思う。
Dockerfileの書き方, 利用する命令, 作成手順を参考にすると、

RUN
DockerfileからImageを作成する際に実行されるコマンド。
Dockerfile内に複数記載可能。
CMD
ImageからContainerを起動する際に実行されるコマンド。
Dockerfile内に1度しか記載できない。
というざっくりした違いがある。

つまり、作成する環境にパッケージをいろいろインストールしておきたい場合はRUN、
コンテナ立ち上げ時にMySQLを起動しておきたい、というような場合はCMD、
ということになる。

CMDと同じくDockerfile内に一度しか記載できず、コンテナ起動時に実行されるコマンドを指定するENTRYPOINTというものがあるが、ここは幼稚園なのでいったん割愛。

参考になるサイト
(Docker) CMDとENTRYPOINTの「役割」と「違い」を解説

Githubから落としてきたら、docker-compose.ymlがついてきたけどこれは?

docker-compose.ymlはざっくりいうと、ImageからのContainerの起動、あるいはDockerfileからImageのビルドも含めて、自動化するファイル。

メリットは少なくとも2つあって、

  • コマンド入力が楽できる
  • 複数のContainerを一度に起動できる

dokcer-compose

docker-compose.ymlに指定するオプションや環境変数を記載しておけば、毎回コマンドでわざわざ指定しなくても、docker-composeファイルを読み込むだけで済むようになる。
またWebサーバーとDBサーバーでそれぞれContainerを起動しようとする際、通常であればそれぞれのContainerに対して起動のコマンド入力をする必要があるが、これもdocker-compose.ymlで一発呼び出しで済む。

bash
# こんなに長いコマンドが
docker run -dp 3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:18-alpine \
  sh -c "yarn install && yarn run dev"
docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:5.7
bash
# これで済むようになる
docker-compose up -d

docker-compose.ymlの中身はこんな感じ

docker-compose.yml
version: "3.7"

services:
  app:
    image: node:18-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

リンクまとめ

6
5
0

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
6
5