ローカル開発用Docker環境をOrbstackに変えてみた【3】自動化シェルスクリプト

開発環境

※ これもGemin先生。ゴルゴ13風にという指定ですww それはそうとして、日本語難しいよね〜ww

そういうわけで開発環境は整いました。

ウェブ制作の案件が来た際に、この開発環境でコーディングに入るに当たって最初にすることがいくつかあります。
例えば、案件名(クライアントやプロジェクト名)がhogefugaで、hogefuga.vagrant.testというurlで開発するとすると、

  1. 作業ディレクトリ[hogefuga]、直下に[public_html]を作る(このへんはお好みで)
  2. ./config/vhosts/ 配下に default.confをコピーし、内容をhogefuga用に編集する
  3. ホストマシンの /etc/hosts ファイルに [127.0.0.1 hogefuga.vagrant.test] を追記

静的サイトや簡易なPHPサイトの場合はここまでで完了。
ワードプレスの場合は以下も必要

  1. MySQLに新規データベースを作る
  2. 1で作った作業ディレクトリ hogefuga/public_html にワードプレスファイルをDLして配置
  3. ワードプレスのconfig.phpを編集

こんな段取りになろうかと思います。
毎回これやるのは面倒なので、シェルスクリプトにして自動化できるものはやっちまいましょう。
シェルなんか滅多に書かないので、基本はChatGPTに仕事してもらって、適宜修正を加えるという方針でいきます。
出来上がったファイルは一番下に掲載してます。


スクリプトの方向性確認と変数の準備

#!/bin/bash

##################################################
# 新規案件開始スクリプト
# ./new-project.sh プロジェクト名 案件タイプ
# 案件タイプは wp, php, static のいずれか
# プロジェクト名は小文字で指定
##################################################

set -e

PROJECT=$1
TYPE=$2
BASE_DIR=~/lamp/docker-compose-lamp/www
VHOST_DIR=~/lamp/docker-compose-lamp/config/vhosts
DOMAIN="${PROJECT}.vagrant.test"
DB="${PROJECT}_db"
DB_HOST=lamp-mysql8  # 説明は下のほうにあります
MYSQL_USER=docker
MYSQL_PASSWORD=docker
MYSQL_ROOT_PASSWORD=tiger

冒頭で、このスクリプトの実行方法を指定します。
スクリプトのファイル名は new-project.sh で、プロジェクト名と案件タイプを渡して実行してやります。例えば、プロジェクト名が[hogefuga]でワードプレス案件であれば、

$ ./new-project.sh hogefuga wp

こういうことですね。

set -e では、終了ステータスが"0"(success)以外なら処理を終了するということで、スクリプトの安全性を担保します。

次に、渡した変数($1、$2)や、.envファイル、docker-compose.ymlで指定した変数や環境変数のうち、このスクリプトで使用するようなものを前もって変数に格納しておきます。

処理

コマンドの評価

if [[ -z "$PROJECT" || -z "$TYPE" ]]; then
  echo "Usage: $0 <project_name> <wp|php|static>"
  exit 1
fi

プロジェクト名、案件タイプという二つの引数のうち、一つでも欠けていたらエラー。
Usage: ./new-project.sh <project_name> <wp|php|static>
といったメッセージを出して処理終了。

プロジェクトフォルダ生成

mkdir -p "$BASE_DIR/$PROJECT/public_html"

これは特に説明いらんでしょう。
-pオプションは、途中のディレクトリも無ければ作るということで、これでプロジェクト名のフォルダとその中にpublic_htmlと、二階層のディレクトリが生成されます。

hostsファイルに追記

HOST_LINE="127.0.0.1 $DOMAIN"
if ! grep -q "$DOMAIN" /etc/hosts; then
  echo "$HOST_LINE" | sudo tee -a /etc/hosts > /dev/null
  echo "[OK] Hosts entry added: $DOMAIN"
else
  echo "[SKIP] Hosts entry already exists: $DOMAIN"
fi

Macの/ets/hosts ファイルにサブドメインを追記。いろいろあって、重複チェック入れてます。
で、これは普通に

sudo echo "127.0.0.1 example.test" >> /etc/hosts

これじゃダメなの?と思うんだけど、どうやらechoはsudo権限でやるけど、そのあと>>でファイルに渡すのはシェルスクリプトの権限でやるので、結局できないらしい。
teeコマンドだと出来るということで、説明を読んだけどなんとなく分かったような気がする程度でいいと思ったwww

コマンドの最後に > /dev/null を付けたのは標準出力に出さないため。

vhost ファイル生成

VHOST_FILE="$VHOST_DIR/${PROJECT}.conf"
cat <<EOF > "$VHOST_FILE"
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html
    ServerName $DOMAIN
    <Directory \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html
    ServerName $DOMAIN
    <Directory \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/cert-key.pem
</VirtualHost>
EOF
echo "[OK] VHost file created: $VHOST_FILE"

これも特に説明いらないかな。ヒアドキュメント便利。


ここまでで、とりあえずサブドメインで hogefuga.vagrant.test にアクセスすることができます。

案件タイプごとの処理

案件タイプによる処理については、case文で条件分けして書きます。

case "$TYPE" in
    wp)
        ほにゃらら
        ;;
    php)
        ほにゃらら
        ;;
    static)
        ほにゃらら
        ;;
    *)
        ほにゃらら
        ;;
esac

こんな感じです。ややこしいのはワードプレスの時だけ。見ていきましょう。

case ワードプレス案件

メモリ不足回避

# WP-CLI メモリ増強
export WP_CLI_PHP_ARGS='-d memory_limit=512M'

WP_CLI_PHP_ARGSというのは、 wp-cli が内部で PHP を呼び出すときに追加するオプションを指定できる環境変数
だそうで、「WordPress CLI を動かすときだけメモリ制限を 512M にする」 という効果らしい。
ワードプレス本体のダウンロードでメモリ不足になってスタックすることがあるので、増やしておきます。

ワードプレス日本語版本体ダウンロード

 WP_PATH="$BASE_DIR/$PROJECT/public_html"
 if [ ! -f "$WP_PATH/wp-config-sample.php" ]; then
     wp core download --locale=ja --path="$WP_PATH"
     echo "[OK] WordPress downloaded"
 else
     echo "[SKIP] WordPress already exists at $WP_PATH"
 fi

ここでも重複チェックを入れています。/etc/hostsの時もそうなんですけど、何らかの理由でエラーが出て全ての処理を完了できなかった時に、こうしたファイルや記述が残っている場合は重複しないようにしたいんですよね。
一応、wp-config-sample.phpファイルの存在で切り分けてるんですけど、まあ、そんな感じで。

MySQL データベース作成

    docker exec -i "$DB_HOST" mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "
    CREATE DATABASE IF NOT EXISTS $DB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
    CREATE USER IF NOT EXISTS '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD';
    GRANT ALL PRIVILEGES ON $DB.* TO '$MYSQL_USER'@'%';
    FLUSH PRIVILEGES;
    "
    echo "[OK] New Database created: $DB"

これも同様の理由で IF NOT EXISTS 付けてます。
最初に変数で用意したように、データベース名はDB="${PROJECT}_db"に決めます。
プロジェクトhogefuga なら hogefuga_db となります。
で、権限ですが、これはもう.envで決めた値のままにしてます。ローカルですからね。
DB_HOSTについてはdocker-compose.ymlにあるdatabaseのコンテナ名を参照します。

  database:
    build:
      context: "./bin/${DATABASE}"
    container_name: "${COMPOSE_PROJECT_NAME}-${DATABASE}"

このcontainer_nameに使われている変数は .env ファイルに記述されているはずですので、そちらを参照。で、

DB_HOST=lamp-mysql8

こうなります。

wp-config.php 作成

ワードプレスCLI(wp-cli)の生成機能に幾つかのパラメータを渡していきます。
テーブルプレフィックスを wp_ のままにするのは個人的には反対で、ランダム生成で3文字いっときます。

 # ランダム3文字のテーブルプレフィックス生成(macOS 対応)
 TABLE_PREFIX="$(LC_CTYPE=C tr -dc a-z </dev/urandom | head -c3)_"

 if [ ! -f "$WP_PATH/wp-config.php" ]; then
    wp config create --dbname="$DB" --dbuser="$MYSQL_USER" \
    --dbpass="$MYSQL_PASSWORD" --dbhost="$DB_HOST" \
    --path="$WP_PATH" --skip-check --dbprefix="$TABLE_PREFIX"
    echo "[OK] wp-config.php created"
else
    echo "[SKIP] wp-config.php already exists"
fi
;;

これでワードプレス案件の下準備も完了。
hogefuga.vagrant.test にアクセスすればワードプレスのインストール画面が表示されます。

静的サイト案件の場合

  static)
    echo "<!DOCTYPE html><html><head><title>$PROJECT</title></head><body><h1>Hello from $PROJECT</h1></body></html>" > "$BASE_DIR/$PROJECT/public_html/index.html"
    ;;

ヘッダーを入れたindex.html を用意します。

PHP案件の場合

  php)
    echo "<?php phpinfo(); ?>" > "$BASE_DIR/$PROJECT/public_html/index.php"
    ;;

phpinfoを表示するindex.phpを用意します。

# Apache 再起動
docker compose restart apache

最後にapacheを再起動。


これで今のところうまくいってます。
最後にファイル全体を貼っておきます。

スクリプトファイル

#!/bin/bash

##################################################
# 新規案件開始スクリプト
# ./new-project.sh プロジェクト名 案件タイプ
# 案件タイプは wp, php, static のいずれか
# プロジェクト名は小文字で指定
##################################################

set -e

PROJECT=$1
TYPE=$2
BASE_DIR=~/WORK/docker-compose-lamp/www
VHOST_DIR=~/WORK/docker-compose-lamp/config/vhosts
DOMAIN="${PROJECT}.vagrant.test"
DB="${PROJECT}_db"
DB_HOST=lamp-mysql8
MYSQL_USER=docker
MYSQL_PASSWORD=docker
MYSQL_ROOT_PASSWORD=tiger

if [[ -z "$PROJECT" || -z "$TYPE" ]]; then
  echo "Usage: $0 <project_name> <wp|php|static>"
  exit 1
fi

# 1. プロジェクトフォルダ作成
mkdir -p "$BASE_DIR/$PROJECT/public_html"

# 2. hosts 追記(重複チェック)
HOST_LINE="127.0.0.1 $DOMAIN"
if ! grep -q "$DOMAIN" /etc/hosts; then
  echo "$HOST_LINE" | sudo tee -a /etc/hosts > /dev/null
  echo "[OK] Hosts entry added: $DOMAIN"
else
  echo "[SKIP] Hosts entry already exists: $DOMAIN"
fi

# 3. vhost ファイル生成
VHOST_FILE="$VHOST_DIR/${PROJECT}.conf"
cat <<EOF > "$VHOST_FILE"
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html
    ServerName $DOMAIN
    <Directory \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html
    ServerName $DOMAIN
    <Directory \${APACHE_DOCUMENT_ROOT}/$PROJECT/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/cert-key.pem
</VirtualHost>
EOF
echo "[OK] VHost file created: $VHOST_FILE"

# 5. 案件タイプごとの処理
case "$TYPE" in
  wp)
    # WP-CLI メモリ増強
    export WP_CLI_PHP_ARGS='-d memory_limit=512M'
    # WordPress 日本語版ダウンロード
    WP_PATH="$BASE_DIR/$PROJECT/public_html"
    if [ ! -f "$WP_PATH/wp-config-sample.php" ]; then
        wp core download --locale=ja --path="$WP_PATH"
        echo "[OK] WordPress downloaded"
    else
        echo "[SKIP] WordPress already exists at $WP_PATH"
    fi

    # MySQL データベース作成(mysql_native_password)
    docker exec -i "$DB_HOST" mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "
    CREATE DATABASE IF NOT EXISTS $DB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
    CREATE USER IF NOT EXISTS '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD';
    GRANT ALL PRIVILEGES ON $DB.* TO '$MYSQL_USER'@'%';
    FLUSH PRIVILEGES;
    "
    echo "[OK] New Database created: $DB"

    # wp-config.php 作成

    # ランダム3文字のテーブルプレフィックス生成(macOS 対応)
    TABLE_PREFIX="$(LC_CTYPE=C tr -dc a-z </dev/urandom | head -c3)_"

    if [ ! -f "$WP_PATH/wp-config.php" ]; then
        wp config create --dbname="$DB" --dbuser="$MYSQL_USER" \
        --dbpass="$MYSQL_PASSWORD" --dbhost="$DB_HOST" \
        --path="$WP_PATH" --skip-check --dbprefix="$TABLE_PREFIX"
        echo "[OK] wp-config.php created"
    else
        echo "[SKIP] wp-config.php already exists"
    fi
    ;;
  php)
    echo "<?php phpinfo(); ?>" > "$BASE_DIR/$PROJECT/public_html/index.php"
    ;;
  static)
    echo "<!DOCTYPE html><html><head><title>$PROJECT</title></head><body><h1>Hello from $PROJECT</h1></body></html>" > "$BASE_DIR/$PROJECT/public_html/index.html"
    ;;
  *)
    echo "Unknown type: $TYPE. Use wp, php, or static."
    exit 1
    ;;
esac

# Apache 再起動
docker compose restart apache

echo "[DONE] Project '$PROJECT' ($TYPE) is ready at http://$DOMAIN/"

開発環境Docker,Orbstack,シェル

Posted by YANAGIDAryosuke