みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Dev ContainerでDocker Composeを使いデータベースを起動する

Visual Studio Codeの拡張機能Remote - Containersを使用して,Dev ContainerでDocker Composeを使いPostgresデータベースを起動して,Pythonから操作してみます.

環境

MacOSからUbuntu ServerのDocker engineにリモート接続してVScodeで操作します.

% docker version
Client:
 Cloud integration: v1.0.22
 Version:           20.10.13
 API version:       1.41
 Go version:        go1.16.15
 Built:             Thu Mar 10 14:08:44 2022
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.15
  Built:            Thu Mar 24 01:45:53 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.5.11
 runc:
  Version:          1.0.3
 docker-init:
  Version:          0.19.0

ソースコード

.devcontainer/devcontainer.json

{
    "name": "Python3 and Postgres",
    "dockerComposeFile": "docker-compose.yml",
    "service": "workspace",
    "settings": {},
    "extensions": [
        "ms-azuretools.vscode-docker",
        "ms-python.python"
    ],
    "remoteUser": "vscode",
    "postCreateCommand": "pip install --user -r requirements.txt"
}

dockerComposeFileを指定して,デフォルトのDockerfileを使用するのではなく,docker-compose.ymlに切り替えます.

VScodeが接続するコンテナをserviceで指定します.

.devcontainer/docker-compose.yml

version: "3"

services:
  workspace:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    command: sleep infinity
    volumes:
      - pysample-bashhistory:/commandhistory

  postgres:
    image: postgres:12
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
      POSTGRES_PASSWORD: postgres

volumes:
  postgres-data:
  pysample-bashhistory:

workspaceはVSCodeが接続する対象となるコンテナですので,起動したら終了しないようにしたり,各種開発用のパッケージをインストールしたりします.

workspaceのdockerfileの相対パスが一見まどろっこしいですが,プロジェクトの任意のファイルにアクセスできるよう,contextはプロジェクトのルートディレクトリに設定しておくべきです.

postgresは初期パスワードの設定が必須なので,環境変数で指定します*1

pysample-bashhistoryはbashの履歴を保存するための名前付きボリュームです.

.devcontainer/Dockerfile

FROM mcr.microsoft.com/vscode/devcontainers/python:3.9-bullseye

ARG USERNAME=vscode
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
    && mkdir /commandhistory \
    && touch /commandhistory/.bash_history \
    && chown -R $USERNAME /commandhistory \
    && echo $SNIPPET >> "/home/$USERNAME/.bashrc"

Dev Container用の各種コンテナイメージはマイクロソフト社が公開してくれていますので,利用します*2

pysample-bashhistoryにbashの履歴を保存するよう設定しておきます.

requirements.txt

psycopg2

PythonでPostgresを使用するためにpsycopg2をインストールします.

main.py

import psycopg2

connection = psycopg2.connect(
    host="postgres",
    port="5432",
    dbname="postgres",
    user="postgres",
    password="postgres",
)
cursor = connection.cursor()
cursor.execute("SELECT version();")
record = cursor.fetchone()[0]
print(f"You are connected to {record}")

これをターミナルから実行すると,以下のような出力が得られました.

vscode ➜ /workspaces/pysample (master) $ python main.py
You are connected to PostgreSQL 12.10 (Debian 12.10-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

docker-compose.ymlのnetwork_modeの設定

network_modeを設定すればlocalhostで別のコンテナにアクセスできるようになると記載されています*3.これを設定しなくても,Docker Composeの機能としてサービス名でアクセスできます*4.上記のソースコードではhost=postgresを指定してアクセスしています.

Docker from DockerやDocker in Dockerとの比較

複数のコンテナを扱う方法として,Docker from DockerやDocker in Dockerが存在しますが,ややこしいマウントを設定したり,キャッシュが効かなかったりするなど,いずれもデメリットがあります.Dev ContainerでDocker Composeを使用する上記の方法は,Docker Composeで複数のコンテナを起動して,そのうちの1個のコンテナをDev ContainerとしてVSCodeから操作するだけですので,とてもシンプルな構成です*5

non-rootユーザー

mcr.microsoft.com/vscode/devcontainers/pythonがnon-rootユーザーに設定されているので追加の操作は不要みたいです*6

参考