Docker入門

Dockerとは

Dockerは仮想環境を構築するためのツールで、OS上に「コンテナ」と呼ばれる仮想環境を構築できる。このコンテナ型の仮想環境では、ホストOSのカーネルを利用してあたかもゲストOSがあるように仮想環境を作り上げる。ゲストOSが不要になるため、一般的な仮想環境と比較して軽量で高速に仮想環境を利用できる。

Notion Image

Dockerをインストールする

  • 以下のリンクを参考にDocker Desktopをインストールする Docker Desktopのインストール

  • VSCodeでDockerを使う

    【準備】拡張機能のインストール

  • VSCodeの拡張機能「Docker」をインストールする
  • Notion Image

  • VSCodeの拡張機能「Remote Development」をインストールする
  • Notion Image

    【基礎編】簡単なサンプルコンテナを動かす

  • 作業用ディレクトリ「venv_docker_sample1」を作成し、VSCodeで作業用ディレクトリを開く
  • 以下のようなファイル構成で設定ファイル群を作成していく

    venv_docker_sample1
        ├ .devcontainer
        |    ├ python
        |    |  ├ Dockerfile
        |    |  └ requirements.txt
        |    ├ compose.yml
        |    └ devcontainer.json
        └ python
            └ src
               └ sample.py

    ※ 各ファイルの簡単な説明

  • Dockerfile:pythonコンテナのイメージの設定を記述する。
  • requirements.txt:インストールするpythonモジュール群を記述する。
  • compose.yml:pythonコンテナ立ち上げ時の設定を記述する。
  • decontainer.json:コンテナ開発環境用の設定を記述する。
  • sample.py:pythonサンプルコードを記述する。

  • 「venv_docker_sample1」の配下に以下のファイル群を作成する
  • # .devcontainer/python/Dockerfile
    
    FROM python:3.11-slim
    WORKDIR /tmp/work
    COPY requirements.txt ${PWD}
    RUN pip install -r requirements.txt
    # .devcontainer/python/requirements.txt
    
    numpy == 1.24.3
    matplotlib == 3.7.1
    # .devcontainer/compose.yml
    
    services:
      python:
        image: ex21/python:1.0
        build: ./python
        container_name: 'ex21-python'
        stdin_open: true
        tty: true
        working_dir: '/tmp/waaork'
        volumes:
          - ../python:/tmp/work
    // .devcontainer/devcontainer.json
    
    {
        "name": "Python Basic Project",
        "dockerComposeFile": "compose.yml",
        "service": "python",
        "workspaceFolder": "/tmp/work",
        "customizations": {
            "vscode": {
                "extensions": [
                    "ms-python.python"
                ],
                "settings": {
                    "editor.tabSize": 4
                }
            }
        }
    }
    # python/sample.py
    
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(0, 100, 0.5)
    Hz = 5.
    y = np.sin(2.0 * np.pi * (x * Hz) / 100)
    
    plt.plot(x, y)
    plt.savefig('test.png')

  • 「コンテナーで再度開く」を押し、コンテナの起動と接続を実施する
  • Notion Image

  • 右下にコンテナ名が表示され、接続が成功したことを確認する
  • Notion Image

  • コンテナ内の変更がローカル環境に反映されることを確認する
  • Notion Image

  • ターミナルを開いて、以下のコマンドを実行する
  • $ python sample.py
    Notion Image

  • エラーが出ることなくpythonプログラムが実行され、pngファイルが生成されることを確認する
  • Notion Image

  • 「リモート接続を終了する」を押し、コンテナを閉じる
  • Notion Image

  • 作業用ディレクトリ「venv_docker_sample1」を再度VSCodeで開き、他の人が同じ環境を再現できるようにGithubにプッシュする
  • Notion Image

  • 不要になったコンテナとイメージを削除する 後述の「コンテナとイメージの削除」を参照

  • 【発展編】Django×PostgreSQLコンテナを動かす

  • 作業用ディレクトリ「venv_docker_sample2」を作成し、VSCodeで作業用ディレクトリを開く
  • 以下のようなファイル構成で設定ファイル群を作成していく

    venv_docker_sample2
        ├ .devcontainer
        |    ├ web
        |    |  ├ Dockerfile
        |    |  └ requirements.txt
        |    ├ .env
        |    ├ compose.yml
        |    └ devcontainer.json
        ├ db
        |  └ init
        |      ├ 01_create_tables.sql
        |      ├ 02_insert_data.sql
        |      └ 03_settings.sql
        ├ web
        └ .gitignore

    ※ 各ファイルの簡単な説明

  • Dockerfile:djangoコンテナのイメージの設定を記述する。
  • requirements.txt:インストールするpythonモジュール群を記述する。
  • .env:環境変数設定を記述する。
  • compose.yml:コンテナ立ち上げ時の設定を記述する。
  • decontainer.json:コンテナ開発環境用の設定を記述する。
  • 01_create_tables.sql:テーブル作成用SQL。
  • 02_insert_data.sql:データ作成用SQL。
  • 03_settings.sql:タイムゾーンの設定用SQL。
  • .gitignore:gitプッシュ時に無視するファイルを記述する。

  • 「venv_docker_sample2」の配下に以下のファイル群を作成する
  • # .devcontainer/web/Dockerfile
    
    # M1Macの場合は以下を指定
    # FROM python:3.11
    # それ以外の場合は以下を指定
    FROM python:3.11-slim
    
    # パッケージのインストール
    RUN apt-get update -qq \
     && apt-get install -y --no-install-recommends \
        tzdata sudo\
     && rm -rf /var/lib/apt/lists/*
    
    # モジュールのインストール
    WORKDIR /tmp/work
    COPY requirements.txt ${PWD}
    RUN pip install -U pip \
     && pip install -r requirements.txt
    
    # 環境変数の定義
    ENV TZ="Asia/Tokyo"
    
    # 一時変数の定義
    ARG USERNAME=user1
    ARG PASSWORD=user1
    ARG GROUPNAME=user1
    ARG UID=1000
    ARG GID=1000
    
    # 一般権限のユーザーを追加
    RUN groupadd -g ${GID} ${GROUPNAME} \
     && useradd -u ${UID} -g ${GID} -G sudo -m -s /bin/bash ${USERNAME} \
     && echo ${USERNAME}:${PASSWORD} | chpasswd \
     && echo "%${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    
    # ユーザーの切替
    USER ${USERNAME}
    # .devcontainer/web/requirements.txt
    
    django == 4.2.2
    # M1Macの場合は以下を指定
    # psycopg2
    # それ以外の場合は以下を指定
    psycopg2-binary == 2.9.6
    # .devcontainer/.env
    
    POSTGRES_DB=postgres
    POSTGRES_USER=postgres
    POSTGRES_PASSWORD=postgres
    # .devcontainer/compose.yml
    
    services:
      db:
        image: postgres:alpine3.18
        container_name: "django-db"
        expose: 
          - "5432"
        environment:
          - TZ=Asia/Tokyo
          - POSTGRES_DB=${POSTGRES_DB}
          - POSTGRES_USER=${POSTGRES_USER}
          - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
        volumes:
          - ../db/database:/var/lib/postgresql/data
          - ../db/init:/docker-entrypoint-initdb.d  
      web:
        image: django/web:1.0
        build: ./web
        container_name: "django-web"
        ports:
          - 8001:8000
        environment:
          - DEBUG=1
        depends_on:
          - db
        stdin_open: true
        tty: true
        volumes:
          - ../web:/home/user1/dev
    // .devcontainer/devcontainer.json
    
    {
      "name": "Django Web",
      "dockerComposeFile": "compose.yml",
      "service": "web",
      "workspaceFolder": "/home/user1/dev",
      "customizations": {
        "vscode": {
          "extensions": [
            "ms-python.python"
          ],
          "settings": {
            "editor.tabSize": 4
          }
        }
      }
    }
    /* db/init/01_create_tables.sql */
    
    create table book
    (
      id serial NOT NULL PRIMARY KEY,
      title text,
      insert_timestamp timestamp with time zone
    );
    /* db/init/02_insert_data.sql */
    
    INSERT INTO book VALUES(DEFAULT, 'プログラミング言語C', current_timestamp);
    INSERT INTO book VALUES(DEFAULT, 'やさしいコンピューター科学', current_timestamp);
    INSERT INTO book VALUES(DEFAULT, 'ゲーデル、エッシャー、バッハ―あるいは不思議の環', current_timestamp);
    INSERT INTO book VALUES(DEFAULT, 'TeXブック コンピュータによる組版システム', current_timestamp);
    INSERT INTO book VALUES(DEFAULT, '人月の神話 狼人間を撃つ銀の弾はない', current_timestamp);
    /* db/init/03_settings.sql */
    
    set timezone to 'Asia/Tokyo';
    # .gitignore
    
    /db/database
    /web/log

  • 「コンテナーで再度開く」を押し、コンテナの起動と接続を実施する
  • Notion Image

  • 右下にコンテナ名が表示され、接続が成功したことを確認する
  • Notion Image

  • タイミナルを開いて、以下のコマンドを順次実行する
  • $ django-admin startproject myprj .
    $ django-admin startapp myapp

  • 設定ファイルのINSTALLED_APPSに作成したアプリを追加する
  • # myprj/settings.py
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    
        'myapp', # アプリを追加
    ]

  • 設定ファイルのDATABASESをPostgreSQLに変更する
  • # myprj/settings.py
    
    # DATABASES = {
    #     'default': {
    #         'ENGINE': 'django.db.backends.sqlite3',
    #         'NAME': BASE_DIR / 'db.sqlite3',
    #     }
    # }
    
    DATABASES = {
      'default': {
          # M1Macの場合は以下を指定
          # 'ENGINE': 'django.db.backends.postgresql',
          # それ以外の場合は以下を指定
          'ENGINE': 'django.db.backends.postgresql_psycopg2',
          'NAME': 'postgres',
          'USER': 'postgres',
          'PASSWORD': 'postgres',
          'HOST': 'django-db',
          'PORT': '5432',
      }
    }

  • Bookモデルを追加する
  • # myapp/models.py
    
    class Book(models.Model):
        title = models.TextField(blank=True, null=True)
        insert_timestamp = models.DateTimeField(blank=True, null=True)
    
        class Meta:
            managed = False
            db_table = 'book'

  • 管理画面からBookモデルを参照できるようにする
  • # myapp/admin.py
    
    from .models import Book
    admin.site.register(Book)

  • 以下のコマンドを順次実行し、マイグレーションを実施する
  • $ python manage.py makemigrations
    $ python manage.py migrate

  • 以下のコマンドを実行し、スーパーユーザーを作成する
  • $ python manage.py createsuperuser
    
    # Username:admin
    # Email address:admin@example.com
    # Password:<任意のパスワード>
    # Password(again):<任意のパスワード>
    # Superuser created successfully.

  • 以下のコマンドを実行し、開発用サーバーを起動する
  • $ python manage.py runserver 0.0.0.0:8000

  • 以下のリンクから管理画面にアクセスして、コンテナ内のDBにアクセスできていることを確認する http://127.0.0.1:8001/admin
  • Notion Image
    Notion Image

  • 「リモート接続を終了する」を押し、コンテナを閉じる
  • Notion Image

  • 作業用ディレクトリ「venv_docker_sample2」を再度VSCodeで開き、他の人が同じ環境を再現できるようにGithubにプッシュする
  • Notion Image

  • 不要になったコンテナとイメージを削除する 後述の「コンテナとイメージの削除」を参照

  • コンテナとイメージの削除

  • 左のDockerアイコンを押すと作成済みのコンテナ一覧とイメージ一覧が表示される
  • Notion Image

  • 対象のコンテナを右クリックして「Compose Down」を押す
  • Notion Image

  • 対象のイメージを右クリックして「Remove」を押す
  • Notion Image

    エラーが出る場合

    設定ファイルが正しく記述されているにも関わらず、コンテナ立ち上げ時にエラーが出る場合がある。その際、コンテナの名前や使用しているportが重複していることが原因である場合が多く、以前作成したコンテナやイメージを削除するとうまくいくことがある。

    参考資料


    著者画像

    ゆうき

    2018/04からITエンジニアとして活動、2021/11から独立。主な使用言語はPython, TypeScript, SAS, etc.