VSCode Remote ContainersでLaravel開発環境を構築

Table of Content

はじめに

開発環境にDockerを使う方は多いと思います。Dockerを使うメリットとしては、

  • ローカル環境にインストールは不要
  • 開発環境が作って壊せる
  • バージョンがプロジェクトに合わせることができる
  • ミドルウェアの構成を含めてプロジェクトメンバとシェアできる

このようなメリットでDockerを開発環境を使う人が多いのでは無いでしょうか。
Dockerを使って開発環境を使うとなると、ソースコードをローカル環境でマウントして使うのが一般的だと思います。
しかし、次の点がデメリットとして出てくるかと思います。

  • Dockerが動くユーザがrootや他uidであるため、ローカル環境で取り回しでsudoが必要
  • コンテナ内でコマンドが必要になると「docker exec」「docker-compose exec」で動かす必要がある
  • デバッグ等ひと工夫が必要である

こんなデメリットを打ち消すのがVSCodeの拡張機能である「Remote Container」です。
「Remote Containers」はデメリットを打ち消すだけでなく、

  • 「.gitconfig」をローカルと同じ環境にしてくれる
  • ssh-agent(ssh-agentについてはこちらを参照)が上がっていればsshもローカル環境に合わせてくれる
  • デバッグは工夫いらずで使用することができる
  • VSCodeの拡張機能はコンテナにインストールして使うのでローカル環境にインストールは不要
  • VSCodeの拡張機能含めてプロジェクトメンバと共有できる

などとdockerのメリットを存分に発揮してくれます。
本記事では「Remote Containers」でLaravelの開発環境を構築してみたいと思います。

まずは 環境を作ってみる。

前提条件

本記事では以下の環境で作成しています。

ソフトウェア バージョン
os Ubuntu 20.04 Desktop
docker 20.10.0
docker-compose 1.25.0
VSCode 1.52.1
Remote Containers v0.154.1

完全にDockerクローズで環境ができるので、Windowsユーザでも有用な開発環境だと思います。

Renmote Containersインストール

「Remote Containers」のインストールについては、多くの方が記事にしているので本記事では触れません。

Remote Containersの環境構築

こんな感じでファイルを作成していきます。

.
├── docker
│   ├── app
│   │   ├── 20-xdebug.ini
│   │   ├── Dockerfile
│   │   └── php.ini
│   └── web
│       └── default.conf
└── docker-compose.yml

docker-compose.yml

「docker-compose.yml」はこんな感じで作成します。

version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - app-data:/var/www/html
    depends_on:
      - app
  app:
    build: ./docker/app
    environment:
      LOG_CHANNEL: stderr
      DB_CONNECTION: "pgsql"
      DB_HOST: "db"
      DB_PORT: "5432"
      DB_DATABASE: "laravel"
      DB_USERNAME: "docker"
      DB_PASSWORD: "docker"
    ports:
      - "8000:8000"
    volumes:
      - app-data:/var/www/html
    depends_on:
      - db
  db:
    image: postgres:12
    environment: 
      TZ: "Asia/Tokyo"
      POSTGRES_USER: "docker"
      POSTGRES_PASSWORD: "docker"
      POSTGRES_DB: "laravel"
    volumes: 
      - db-data:/var/lib/mysql
volumes:
  app-data:
  db-data:

DBはherokuデプロイを狙ってpostgresを使っていますが、イメージをmysqlにすればMySQLへの切り替えも簡単かと思います。
PHPはfpmで構築しました。Webはnginxで行います。
私はソースコードをローカルにマウントしないで、Dockerのボリューム機能を使ってマウントしています。VSCodeはコンテナ内のファイルを編集しますし、.gitconfigもローカル環境の内容をコンテナ内で展開するので、ソースコードも含めてコンテナ内で全て作業します。

nginx環境

「./docker/web/default.conf」はPHP-FPMで良く使われる内容です。

erver {
    listen 80;
    root /var/www/html/public;
    index index.php index.html index.htm;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    access_log /dev/stdout;。
    error_log /dev/stderr;
}

Dockerfile

PHP-FPMで使用するDockerfilkeはこんな感じです。

FROM php:7.4-fpm

ENV TZ=UTC \
    LANG=en_US.UTF-8 \
    LANGUAGE=en_US.en \
    LC_ALL=en_US.UTF-8 \
    PATH=/composer/vendor/bin:$PATH

COPY --from=composer /usr/bin/composer /usr/bin/composer

RUN set -x \
 && apt update \
 && apt upgrade -y \
 && apt install -y --no-install-recommends git zip unzip libicu-dev libonig-dev libzip-dev locales libpq-dev \
 && apt clean \
 && rm -rf /var/cache/apt \
 && locale-gen en_US.UTF-8 \
 && localedef -f UTF-8 -i en_US en_US.UTF-8 \
 && docker-php-ext-install pdo_pgsql intl zip bcmath \
 && pecl install xdebug \
 && docker-php-ext-enable xdebug \
 && curl -sL https://deb.nodesource.com/setup_12.x | bash - \
 && apt install -y nodejs \
 && usermod -s /bin/bash www-data \
 && chown -R www-data:www-data /var/www

COPY ./php.ini /usr/local/etc/php/php.ini
COPY ./20-xdebug.ini /usr/local/etc/php/conf.d/20-xdebug.ini

USER www-data

WORKDIR /var/www/html

PHP-FPMがユーザ「www-data」で動くので、

  • 「usermode」コマンドでwww-dataユーザのシェルを変更
  • www-dataのホームディレクトリが「/var/www」なので、ディレクトリオーナーを変更
  • Dockerfileの「USER」でユーザをwww-dataに変更
  • Laravelは「/var/www/html」に展開するので、Dockerfileの「WORKDIR」で変更
  • Laravelは「laravel install」ではなく「composer create-project」でインストール

php.ini

「php.ini」はタイムゾーンとmbstringの設定を行っているだけです。

[Date]
date.timezone = ${TZ}
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

xdebu.ini

デバッグを行うので、「20-xdebug.ini」を追加です。

xdebug.client_host=localhost
xdebug.client_port=9003
xdebug.idekey=PHPSTORM 
xdebug.mode=develop,debug
xdebug.start_with_request=yes
xdebug.log=/tmp/xdebug.log

2021/1/20更新) XDebug3に書き換えました。

devcontainer.json

「Remote Containers」の肝である「./.devcontainer/devcontainer.json」の定義です。

{
    "name": "Laravel",
    "dockerComposeFile": ["../docker-compose.yml"],
    "service": "app",
    "workspaceFolder": "/var/www/html",
    "settings": {
        "terminal.integrated.shell.linux": null
    },
    "extensions": [
        "mikestead.dotenv",
        "felixfbecker.php-debug",
        "neilbrayfield.php-docblocker",
        "bmewburn.vscode-intelephense-client",
        "onecentlin.laravel5-snippets",
        "onecentlin.laravel-blade",
        "ryannaddy.laravel-artisan",
        "mhutchie.git-graph"
    ],
    "remoteUser": "www-data"
}

ポイントとしては次の通りです。

  • 'dockerComposeFile'で使用する\docker-compose.yml'を指定
  • 'service'で「Remote Containers」が接続するサービスを指定
  • 'workspaceFolder'でコンテナ内の作業フォルダを指定
  • 'extenSions'で「Remote Containers」で使用する拡張機能を指定
  • 'remoteUser'でコンテナ内で使用するユーザを指定

Remote Containersを使う

VSCodeの画面左下をクリックします。

Remote Container起動

コマンドが開くので「Open Folder in Container...」を選択します。

Remote Container起動

フォルダを選択するダイアログが開くので「docer-compose.yml」が存在するフォルダを開きます。
「Remote Containers」が開くとVSCodeは次のような画面になります。

Remote Container画面

VSCodeのターミナルより次のコマンドでLaravelをインストールします。

composer create-project --prefer-dist laravel/laravel .

VSCodeでLaravelがインストール出来たのを確認できます。

Remote Container&Laravel

後はファイルを編集するなりターミナルでartisanを実行するなりすれば良いかと…

最後に

今回は「PHP&Laravel」で紹介してきましたが、「Ruby on Rails」や「Vue」とかでも使えます。開発環境をローカルで揃えるには結構手間ですが(特にWindows)、Dockerを使うことで容易に開発環境を揃えることができます。

「Remote Containers」を使うことによって、開発環境をローカル環境から分離することができるので、最強の開発環境が構築できたと思います。