【Google Cloud】GCE に PostgreSQL + Tailscale を Docker で構築する方法
先日、以下の記事で Google Cloud Compute Engine (以下、GCE)にPostgreSQLを導入する方法について紹介しました。
上記のやり方は GCE に PostgreSQL を直接インストールする方法ですが、色々調べていくうちに「Docker でやった方がよくない?」と思い至ったのでその方法もご紹介します。
(あくまで自分がやりたいことを考えると Docker が適してそうだったというだけなので、単にDBサーバーとして使いたいだけであれば直接インストールでも問題ないと思います)
また、Tailscale もついでに Dockerコンテナに含んでいるので、PostgreSQL 側の設定ファイルをいじらなくても外部から接続できるようにもしてあります。
ローカル環境の準備
Tailscale のインストール
Tailscale は、設定が非常に簡単で個人利用でも無料で使える VPN サービスです。
GCE には Tailscale を Dockerコンテナにしますが、ローカルPCでは GUI や CLI 経由で簡単に操作・ログインするのに都合がよいので直接インストールにしています。
- インストールしてVPN接続する
基本的には以下の記事を参考にしていただければ、インストール&VPN接続は簡単にできると思います。
-
コンソール画面を開く
案内に従って操作すると コンソール画面が開くのでそこまで操作してください。
もし以下の画像のようにローカルPCの VPN接続の後に追加のマシンでの接続の案内が出た場合はスキップしてください。
-
認証キーの作成画面を開く
コンソール画面から上のメニューにある「Settings」→「Keys」→「Auth Keys」の「Generate auth key...」を選択します。
-
認証キーを作成する
デフォルトの設定のまま、「Generate key」を押します。
この設定では認証キーは最初の接続の1回しか使用できませんが、2回目以降の接続は最初の接続で作成された認証情報を利用するため問題ありません。
-
認証キーのコードを控えておく
認証キーの作成が完了するとコードが表示されるので控えておいてください。
後程 docker-compose の設定で使います。
(スキップ可) Docker のインストール
「GCE に Dockerコンテナをデプロイする前にローカル環境で試しておきたい」という方はローカルPCに Docker をインストールしましょう。
「Docker インストール やり方」みたいに検索すればたくさん情報が出てくるので、お使いの環境に適したものを参照してください。
Docker の準備
適当な場所に以下のようなフォルダ構成でフォルダやファイルを作成してください。
sample-docker/
├── docker-compose.yml # Compose本体
└── initdb/
└── init.sql # 初期DB構築SQL
sample-docker は好きな名前で大丈夫です。
Dockerコンテナをデプロイする際に特にオプションを指定しなければ、この名前が Docker Compose のプロジェクト名になります。
version: '3.8'
services:
postgres:
image: postgres:15
container_name: postgres
environment:
POSTGRES_USER: admin_user # 作成するスーパーユーザー名(デフォルトはpostgres)
POSTGRES_PASSWORD: password # スーパーユーザーのパスワード
POSTGRES_DB: game_db # 起動時に自動作成されるデータベース名
ports:
- "5432:5432" # ホストとコンテナ間でポートを直接バインド
volumes:
- pgdata:/var/lib/postgresql/data # PostgreSQLのデータを保持する名前付きボリューム
- ./initdb:/docker-entrypoint-initdb.d # 起動時に実行する初期化SQL(ユーザーや権限設定)
tailscale:
image: tailscale/tailscale
container_name: tailscale
network_mode: "host" # コンテナがホストと同じネットワーク空間で動作(Tailscaleで必須)
cap_add:
- NET_ADMIN # VPN設定などに必要なネットワーク管理権限
- SYS_MODULE # 一部OSでWireGuardモジュールを使うための権限
volumes:
- /dev/net/tun:/dev/net/tun # TUNデバイス(仮想ネットワークインターフェース)を共有
- /var/lib/tailscale:/var/lib/tailscale # Tailscaleの接続情報やセッション状態を永続化(GCE上ではこのパス推奨)
environment:
- TS_AUTHKEY=tskey-auth-xxxxxxxxxxxxxxx # 認証キー(初回接続時にログインなしでVPN接続するためのトークン)
profiles:
- tailscale # 必要な環境でのみ起動するためのプロファイル指定
volumes:
pgdata: # 名前付きボリューム。PostgreSQLのデータファイルを保持
postgres:
の enviroment:
の設定(ユーザー名やパスワード等)は任意のものを設定していただいて大丈夫です。
tailscale:
の enviroment:
の TS_AUTHKEY
は Tailscale の認証キーのコードを設定してください。
profiles:
を設定することで、「特定のコンテナをローカルでは起動せず、GCEでは起動したい」みたいな切り分けが可能です。
-- create user
CREATE USER game_user WITH PASSWORD 'password';
-- grant privileges to game_user
\c game_db
GRANT CONNECT ON DATABASE game_db TO game_user;
GRANT USAGE ON SCHEMA public TO game_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO game_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO game_user;
init.sql
には PostgreSQL で最初に設定しておきたいものを記載してください。
上記の場合は、game_user
というユーザーを作成して game_db
に対する SELECT
, INSERT
, UPDATE
, DELETE
の権限を与えています。
そもそも最初に設定したいものがなければinit.sql
はなくても大丈夫です。
ちなみにこの記事のdocker-compose.yml
では「initdb
フォルダにある SQL を最初に実行する」設定になっているため、init.sql
というファイル名でなくても動きますし SQLファイルが複数あっても動くはずです。
Dockerコンテナのデプロイ
(スキップ可) ローカル環境でのデプロイ
「GCE に Dockerコンテナをデプロイする前にローカル環境で試しておきたい」という方は以下のコマンドを入力してみましょう。
# docker-compose.ymlが置いてあるフォルダに移動
cd ~/sample-docker
# docker-compose.ymlの設定に従ってコンテナを起動(バックグラウンド実行)
docker compose up -d
正常にコンテナがデプロイされていれば、ローカルPCに PostgreSQL がインストールされているのと同じように PostgreSQL にアクセスできるはずです。
docker-compose.yml
で設定した通りのユーザーやデータベースが存在していれば問題ありません。
ちなみに自分は DBeaver で接続確認しました。
その際の接続先の設定は以下の通りです。
項目 | 値 |
---|---|
ホスト | localhost |
ポート | 5432 |
データベース | game_db |
ユーザー |
admin_user または game_user
|
パスワード | 設定したパスワード |
GCE でのデプロイ
-
sample-docker
を.tar.gz
に圧縮する。
先ほど作成したdocker-compose.yml
が置いてあるフォルダを.tar.gz
の形式に圧縮しましょう。
この記事では GCE に対する操作は全てブラウザSSH で行うのですが、ブラウザSSH ではファイル単位でしかアップロードできないので一度.tar.gz
の形式に圧縮する必要があります。 -
GCE のブラウザSSH を開く
Google Cloud の画面の左上のメニューから「Compute Engine」→「VMインスタンス」→「SSH」を選択する等で開けます。 -
GCE のブラウザSSH からファイルをアップロードする
メニューにある「ファイルをアップロード」からsample-docker.tar.gz
をアップロードしてください。
-
GCE 上で展開
ブラウザSSH で以下のコマンドを入力して、.tar.gz
を展開してください。
tar xzf sample-docker.tar.gz
- Docker をインストール(初回のみ)
初期状態では GCE には Docker が入っていないのでインストールします。
# パッケージ更新と事前準備
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
# Docker の GPG キーを追加
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Docker リポジトリを追加
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Docker および Compose Plugin をインストール
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
- インストールが成功したか確認する
以下のコマンドが通ればインストールは成功しています。
# インストール確認
docker --version
docker compose version
- コンテナをデプロイする
以下のコマンドを入力してください。
# docker-compose.ymlが置いてあるフォルダに移動
cd sample-docker
# docker-compose.ymlの設定に従ってコンテナを起動(バックグラウンド実行)
# Tailscaleのコンテナも起動する
sudo docker compose --profile tailscale up -d
-
Tailscale の VPN の接続を確認する
Tailscale のコンソール画面を開いてください。
コンテナの起動が成功していれば、接続しているマシン一覧にローカルPC以外に GCE のインスタンスが追加されているはずです。
-
ローカルPCから GCE の PostgreSQL に接続する
Tailscale の VPN に接続しているローカルPCから GCE の PostgreSQL に接続できるか試してください。
接続先は GCE の外部IPアドレスではなく、Tailscale のコンソールから確認できるアドレスです。
正常にコンテナがデプロイされていれば、PostgreSQL が直接インストールされているのと同じように PostgreSQL にアクセスできるはずです。
docker-compose.yml
で設定した通りのユーザーやデータベースが存在していれば問題ありません。
自分は DBeaver で接続確認したのですが、その際の接続先の設定は以下の通りです。
項目 | 値 |
---|---|
ホスト | 100.xx.xx.xx (Tailscale の GCE 側のアドレス) |
ポート | 5432 |
データベース | game_db |
ユーザー |
admin_user または game_user
|
パスワード | 設定したパスワード |
おわりに
Docker は既にある設定ファイルをちょびっと修正するくらいしか経験がなかったので勉強になりました。
やはり今どきクラウドを使うのであれば Docker は避けて通ってはいけませんね。
また、Tailscale の設定をはじめてやってみたのですが思いのほか簡単で驚きました。
GCE のファイアウォールの設定なしでローカルPCからアクセスできるのは大変助かります。
個人で使う分には無料プランで全く問題ないので今後も使っていこうと思います。他にも何か便利な用途が見つかったら記事にしたいと思います。
Discussion