【自作ブログ】Google Cloud Platform(GCP)の無料枠インスタンスにGhostブログを作成しよう

Google Cloud Platform(GCP)には無料枠のVM インスタンスを作成することができます。

そのインスタンスにDockerを入れて、Docker上でGhost、mysql、caddyで自作ブログを立てていきます。

2025/05現在の条件では画像のようになっています。

参考:https://cloud.google.com/free/docs/free-cloud-features#compute
GCP無料枠の説明画像

e2-microとなりスペックが2 vCPU, 1GB RAMなので大量にアクセスされるサイトには向いてないですね。

個人ブログではいいかもしれないです。


ドメイン名などはお好きに取得してください。自分はお金をかけたくなかったのでMyDNSで取得しました。(将来的にはお名前ドットコムでしっかりしたドメイン名を取りたいです...)

GCPの無料インスタンスを作成する方法はたくさん記事がありますので割愛します。

OSは「Ubuntu 25.04 minimal」で作成しています。

sshをしてターミナルに入ります。

とりあえずパッケージリスト更新をしてから

sudo apt update

Dockerインストール

参考

Docker Engine インストール(Ubuntu 向け)
Ubuntu 上に Docker Engine をインストールする手順を説明。

リポジトリを利用したインストール

sudo apt install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
     | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker Engine のインストール

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

これでインストールできているはずです。バージョン確認のコマンドを打ち込んで表示されるか確認してみてください。

docker -v

Dockerを一般ユーザで実行できるようにするには(管理者権限sudoで操作する場合はやらなくてもいい

dockerグループの確認(出力結果ではまだ誰もグループにいないことが分かります。)

getent group | grep docker
docker:x:999:

一般ユーザーを追加(ユーザー名の箇所は自身のユーザー名)

sudo usermod -aG docker ユーザー名

再度dockerグループの確認(出力結果に追加した自身のユーザー名が表示されていれば成功です。)

getent group | grep docker
docker:x:999:ユーザー名

その後、一度sshを切って再度ログインしなおしてください。


docker-compose.yml を作成

・Caddyは自動でSSL化(Let's Encryptの証明書発行)してくれるのでこの時点でGCPのインスタンスの外部IPアドレスとドメイン名と紐づけしておくといい

Dockerの作業フォルダを作成して移動します。

mkdir docker-ghost
cd docker-ghost

docker-compose.ymlを作成

docker-compose.yml

  services:

  ghost:
    image: ghost:latest
    container_name: ghost
    restart: always
    environment:
      database__client: mysql
      database__connection__host: db
      database__connection__user: root
      database__connection__password: ghostpassword
      database__connection__database: ghost
      url: "https://あなたのドメイン名"
    volumes:
      - ./ghost:/var/lib/ghost/content
      - ./config.production.json:/var/lib/ghost/config.production.json
    expose:
      - "2368"

  db:
    image: mysql:8.0
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ghostpassword
    volumes:
      - ./db:/var/lib/mysql

  caddy:
    image: caddy:alpine
    container_name: caddy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddy_data:/data
      - ./caddy_config:/config

そしたら次にCaddyfileを作成します。

テキストでそのままの名前「Caddyfile」で作成して中身は以下のようにしてください。

Caddyfile

あなたのドメイン名 {

    reverse_proxy ghost:2368 {

        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        header_up Cookie {http.request.header.Cookie}

    }
}

ここまで来たらOK

起動してみてください。

docker compose up -d

起動したら「https://あなたのドメイン名/ghost」にアクセスしてみてください。


動作が重いときはスワップを作成してみてください。

参考

swapfileの追加
目次: 対象の標準OS, swapfileの追加- スワップが存在しない事を確認, スワップファイルを作成, スワップファイルの有効化.. 「さくらのVPS」の標準OSで swapfile を利…

余談

docker-ghostのフォルダ内に「config.production.json」というファイルがあると思います。

Ghostにメール認証機能があり、メール設定が必要になりますので下記記事を参考にしてみてください。

【Ghost】別端末からログインしようとした時に詰まった話
セルフホストでGhostでブログを運用していて別端末からログインしようとしたらずっとグルグルして入れない現象になってしまってました。 最初に初期設定した端末ではCookieを持っているためログイン画面を飛ばしてログインが可能だったのでその端末でしか入れませんでした。 原因は2段階認証があったこと、、 メールアドレスとパスワードを入力後にそのメールアドレス宛に6桁の数字が送られてくる、それを画面遷移後のページに入力が必要になるが、セルフホストしていてメール設定をしていないとグルグルして進まなくなってしまう、、 自分はGhostのメール設定に自身のGmailを利用してメールを飛ばすようにしている。 先ずは、Gmailのアプリパスワードを発行します。 Account settings: Your browser is not supported. その後にGhostの以外ファイルのmailの箇所を編集 「config.production.json」 { “mail”: { “transport”: “SMTP”, “options”: {

Read more

【PowerShell】ローカルアカウントのコマンドのみでドメインアカウントのコマンドプロンプトと管理者権限付きのPowerShellを開く方法

Windowsのローカルアカウントからドメインアカウントでコマンド操作をしたい場合は、基本的にローカルアカウントを一度ログアウトしてから「他のユーザー」からドメインアカウントへ切り替えが必要となります。 そのログイン切り替えが面倒くさいため、ローカルアカウントをログアウトせずにコマンドのみでドメインアカウントのコマンド操作できるPowerShell実行方法を掲載します。 まずはドメインアカウントに管理者権限を付けます。 ローカルアカウトでコマンドプロンプトを管理者権限で開きます。(PowerShellも可) 以下コマンドでドメインアカウントを管理者グループに追加しておきます。 ※「アカウントID」箇所を自身の使うアカウントに書き換えしてください。 net localgroup administrators アカウントID /add 次に、ドメインアカウントのコマンドプロンプトを開きます。 ※「ドメイン名」と「アカウントID」箇所を自身の使うドメインとアカウントに書き換えしてください。 パスワードが求められたらドメインアカウントのパスワードを入力してエンターを押します。

By 管理者

【PowerShell】ファイル名が連番の複数テキストファイルの中身を一度に表示させるコマンド「Get-Content」(for文を利用)

仕事などで大量に送られてきたテキストファイル(証跡など中身を確認しないといけないテキスト)を確認するようなこと稀にありますよね。 今回はそのテキストファイルの中身をPowerShellコマンドで一度に表示する方法をご紹介します。 後半ではテキストファイル内の特定の文字列のみを表示する方法も記載してますので、少しでも需要があればと思っています。 前提 テキストファイルのファイル名が「文字列+連番.txt」などになっていることが理想的です。 「文字列+連番+文字列.txt」のように文字列の間が連番となっていても可能です。 今回の例ではCドライブにtestディレクトリを作成しています。 「C:\test」で実行していますのでご自身の環境に合わせて書き換えてください。 ファイル名:file1.txt ~ file10.txt テキストの中身には「file1」~「file10」と記載しています。 例:「文字列 + 連番.txt」の中身表示 10個連番のテキストファイルの中身を表示します。 ※ファイル数が多い場合は1行目の黄色い箇所の数字を変更してください。 「for

By 管理者

UGREEN NASのDockerで「Tailscale」接続をする方法

UGREEN NAS(DXP2800)を自宅で稼働させています。 外部からTailscaleで接続を実現させたり、 VPNを借りて、VPNでhttp/https接続されたものをTailscale経由で自宅のUGREEN NAS(DXP2800)にリバースプロキシを実現させたく思いました。 ※今回の記事ではUGREEN NAS(DXP2800)のみの設定を記載しています。 UGREEN NAS(DXP2800)のDocker上で「Tailscale」に接続する方法を紹介します。 Tailscaleアカウント作成 先ずは「Tailscale」のアカウントを作成しておいてください。 Tailscale · Best VPN Service for Secure NetworksSecurely connect to anything on the internet with Tailscale. Deploy a WireGuard®-based VPN to achieve point-to-point connectivity that

By 管理者

【n8n】n8nからLINEのbot(Messaging API)でメッセージを送る方法

n8nからLINEのbotにメッセージを送る方法を掲載します。 LINE DevelopersでMessaging APIのアカウントを作成しておいてください。 LINE DevelopersLINE Developersサイトは開発者向けのポータルサイトです。LINEプラットフォームのさまざまな開発者向けプロダクトを利用するための、管理ツールやドキュメントを利用できます。LINEログインやMessaging APIを活用して、アプリやサービスをもっと便利に。LINE Developers n8nで使うノードは「HTTP Request」になります。 HTTP RequestのParametersを設定します。 Method:POST URL:https://api.line.me/v2/bot/message/push Authentication:None Send Query Parameters:オフ Send Headers:オン Specify Headers:Using JSON JSON { "Authorization": "Bearer

By 管理者