DevcontainerでPostgreSQL学習環境を手軽に構築する

DevcontainerでPostgreSQL学習環境を手軽に構築する

Clock Icon2024.12.05

はじめに

データ事業本部ビッグデータチームのyosh-kです。
この記事は「PostgreSQL Advent Calendar 2024」の5日目のエントリです。
最近PostgreSQLでSQLを学習しているときに、Devcontainerを用いた開発環境を作ったのでそれを紹介したいと思います。

https://qiita.com/advent-calendar/2024/postgresql

前提

SQLFluffというSQLのリンターを使用するため、Python3をインストールします。Gitでのプッシュもできることとします。
https://dev.classmethod.jp/articles/sqlfluff-2/

  • Python
  • Git

事前準備

VSCodeをインストールし、Devcontainerの拡張機能も追加しておきます。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

Gitのセットアップも実施します。
https://prog-8.com/docs/git-env

Dockerコンテナを実行できる環境(例:Docker Desktop、Rancher Desktop)が起動した状態にしておきます。私の場合は、Rancher Desktopを使用しています。

https://www.kagoya.jp/howto/cloud/container/rancher_desktop/

実装

実装コードはリポジトリにもありますので、ご参照いただければと思います。私のリポジトリでは、2つのDevcontainerを定義しているため、フォルダを.devcontainer直下で区切っていますが、一つしかない場合は、直下にフォルダは必要ないです。

vscode ➜ /workspaces/.devcontainer (main) $ tree
.
├── cdk-dev
│   ├── Dockerfile
│   └── devcontainer.json
└── postgresql-dev
    ├── Dockerfile
    ├── devcontainer.json
    └── docker-compose.yml

2 directories, 5 files

https://github.com/cm-yoshikikasama/blog_code/tree/main/.devcontainer

.devcontainer/postgresql-dev/devcontainer.json
{
    "name": "postgresql-dev container",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspaces",
    "remoteEnv": {
      "PATH": "${containerEnv:PATH}:/home/vscode/.local/bin"
    },
    "postCreateCommand": "pip install --upgrade pip && pip install sqlfluff",
    "customizations": {
      "vscode": {
        "extensions": [
          "ms-azuretools.vscode-docker",
          "mtxr.sqltools",
          "mtxr.sqltools-driver-pg",
          "dorzey.vscode-sqlfluff",
          // Markdownのリンター
          "davidanson.vscode-markdownlint",
          // Gitの履歴を視覚化
          "donjayamanne.githistory",
          // Gitの機能拡張
          "eamodio.gitlens",
          // CSVファイルの編集
          "janisdd.vscode-edit-csv",
          // Markdownプレゼンテーションツール
          "marp-team.marp-vscode",
          // CSVファイルの表示改善
          "mechatroner.rainbow-csv",
          // 日本語言語パック
          "ms-ceintl.vscode-language-pack-ja",
          // スペルチェッカー
          "streetsidesoftware.code-spell-checker",
          // ファイルアイコンテーマ
          "vscode-icons-team.vscode-icons",
          // Markdown機能拡張
          "yzhang.markdown-all-in-one"
        ],
        "settings": {
          // Gitの自動更新を有効化
          "git.autorefresh": true,
          // VSCodeのカラーテーマ設定
          "workbench.colorTheme": "Visual Studio Dark",
          // セマンティックトークンの色のカスタマイズ
          "editor.semanticTokenColorCustomizations": {},
          // Markdown固有の設定
          "[markdown]": {
            "editor.defaultFormatter": "yzhang.markdown-all-in-one"
          },
          // フォントリガチャを無効化
          "editor.fontLigatures": false,
          // ワークスペースの信頼設定を無効化
          "security.workspace.trust.enabled": false,
          // ファイル末尾に改行を挿入
          "files.insertFinalNewline": true,
          // ファイルアイコンテーマの設定
          "workbench.iconTheme": "vscode-icons",
          "sqltools.connections": [
            {
              "name": "DevContainer PostgreSQL",
              "driver": "PostgreSQL",
              "previewLimit": 50,
              "server": "localhost",
              "port": 5432,
              "database": "devcontainer_db",
              "username": "postgres",
              "password": "postgres"
            }
          ],
          "[sql]": {
            "editor.defaultFormatter": "dorzey.vscode-sqlfluff",
            "editor.formatOnSave": false
          },
          "sqlfluff.config": "/workspaces/.devcontainer/postgresql-dev/.sqlfluff",
          "sqlfluff.executablePath": "/home/vscode/.local/bin/sqlfluff",
          "sqlfluff.linter.run": "onSave", // ファイル保存時に自動実行
          "sqlfluff.formatter.lineLength": 80, // SQLコードの整形ルール
          "sqlfluff.experimental.format.executeInTerminal": true,
          "sqlfluff.format.enabled": true
        }
      }
    }
  }

Markdownやcsvの拡張機能は私の好みで入れてあるので、不要であれば削除いただいて構いません。

.devcontainer/postgresql-dev/docker-compose.yml
version: "3.8"

services:
  app:
    build:
      context: ..
      dockerfile: postgresql-dev/Dockerfile

    volumes:
      - ../..:/workspaces:cached

    # Overrides default command so things don't shut down after the process ends.
    command: sleep infinity

    # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
    network_mode: service:db

  db:
    image: postgres:latest
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: devcontainer_db
      POSTGRES_PASSWORD: postgres

volumes:
  postgres-data:

Pythonとpostgresql-clientをインストールするアプリケーションコンテナ(app)とPostgreSQLデータベースコンテナ(db)を定義しています。アプリケーションコンテナはデータベースと同じネットワークで実行され、ワークスペースのディレクトリをマウントしています。データベースコンテナは永続的なデータ保存のためのボリュームを持ち、基本的な環境変数(ユーザー名、データベース名、パスワード)を設定しています。

Dockerfile
FROM mcr.microsoft.com/devcontainers/python:1-3.11-bullseye

ENV PYTHONUNBUFFERED 1

RUN apt-get update && apt-get install -y postgresql-client

Dockerfileでは、Pythonとpostgresql-clientをインストールします。

.sqlfluff
[sqlfluff]
templater = raw
dialect = postgres
max_line_length = 200
output_line_length = 200
sql_file_exts = .sql
# バイト制限解除
large_file_skip_byte_limit = 0

# ルールの中から取り除くものを選ぶ
exclude_rules = 
    # sqlfluff fixでカラムの順序を変えないようにするための設定
    structure.column_order
    ,ambiguous.column_count
    ,structure.using
    # Salesforceはキャメルケースでlowerにすると読みにくくなるため追加
    ,capitalisation.identifiers

[sqlfluff:indentation]
indent_unit = space
tab_space_size = 4

[sqlfluff:rules:layout.long_lines]
# コメント行は長くても可とする。URLなどが入るため
# 行の長さに関してコメント行は無視する
ignore_comment_lines = True 
# 行の長さに関してコメント句は無視する
ignore_comment_clauses = True 

[sqlfluff:layout:type:comma]
# 先頭のカンマの強制
line_position = leading
# 前カンマの場合スペース入れない
spacing_after = touch

[sqlfluff:rules:capitalisation.keywords]
# 予約語の大文字小文字
capitalisation_policy = upper

[sqlfluff:rules:capitalisation.functions]
# 関数名の大文字小文字
extended_capitalisation_policy = upper

[sqlfluff:rules:capitalisation.literals]
# リテラル値 (null・true・false) の大文字小文字
capitalisation_policy = upper

[sqlfluff:rules:capitalisation.types]
# データ型の大文字小文字
extended_capitalisation_policy = upper

sqlfluffファイルをお好みに合わせて設定します。以下が参考になりました。
https://docs.sqlfluff.com/en/stable/reference/rules.html
https://laid-back-scientist.com/sqlfluff

実行結果

ローカルでリポジトリを開いたタイミングで右下に「コンテナーで再度開く」というポップアップが表示されるので、そちらを押下して、Devcontainerを起動します。
Screenshot 2024-11-30 at 17.21.00

問題なく起動に成功しました。
Screenshot 2024-11-30 at 17.24.18

SQLTOOLSもインストールできています。
Screenshot 2024-11-30 at 17.24.46

Python、psql、sqlfluffもインストールできていることを確認できました。
Screenshot 2024-11-30 at 17.31.14

試しにサンプルデータを格納して、select文をファイルとして保存してみます。

CREATE TABLE mst_users(
    user_id         varchar(255)
  , register_date   varchar(255)
  , register_device integer
);

INSERT INTO mst_users
VALUES
    ('U001', '2016-08-26', 1)
  , ('U002', '2016-08-26', 2)
  , ('U003', '2016-08-27', 3)
;
select 
    user_id
  , register_date
  , register_device
from mst_users

;

するとSQLFluffのリンターが機能し、アラートが複数出ました。selectが大文字である必要があります。
Screenshot 2024-11-30 at 17.36.59

別の行でもインデントのアラートが出ています。
Screenshot 2024-11-30 at 17.37.07

全て修正した状態にしました。
Screenshot 2024-11-30 at 17.37.40

実行したところ、SQLTOOLで確認できました。
実行はSQLを範囲選択して、Ctrl + Eでできます。
Screenshot 2024-11-30 at 17.37.50

最後に

削除もコンテナを削除するだけなので、簡単に試すことができます。これでどんどんSQLを学んでいきたいと思いました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.