はじめに

Dockerdirenvを利用することで、ほぼphpenvと同じようなことが実現できた。

Docker Compose

Dockerでちまちまコマンドを叩くのは苦手なので、Docker Composeを用意する。
docker-compose.yamlはこんな感じ。

version: "3.7"
services:
  php:
    image: php:cli
    ports:
      - "8000"
    volumes:
      - .:/usr/src/myapp
      - /etc/localtime:/etc/localtime:ro
      - /etc/group:/etc/group:ro
      - /etc/passwd:/etc/passwd:ro
    working_dir: /usr/src/myapp
    user: "${DOCKER_UID}:${DOCKER_GID}"

まあ、どこにでもあるような設定ファイルになっている。
細かい項目の説明はこんな感じ。

image

好きなバージョンのイメージを持ってくる。 もちろん自前でDockerfile用意してイメージをビルドしても良い。

ports

PHPのビルドインサーバを利用する場合は、そのポート番号を設定しておくと良い。
利用しないならポート使わない気がするんで、無しで良いのでは。

volumes

Docker for Macだとあんまり関係ないかもだけど、Linux上だとuser定義してあげないとファイルのパーミッション周りでいろいろ不便。
ついでにタイムゾーンの設定もしてある。

working_dir

Docker HubのPHPの公式ページを参照。
なんでも良いと思う。

user

実行ユーザーの指定。
環境変数はdirenvで指定している。
これまたお好みなので、直接IDを指定しても良い。

direnv

direnvでやりたいことは、特定のディレクトリに移動したら、docker-compose.yamlで指定されたPHPをDockerを意識することなく違和感なく利用できるようにする。
そう、phpenvみたいに。

具体的には、特定のディレクトリに移動すれば、

$ php ./foobar.php

みたいにあたかもPHPがインストールされているように使いたい。

設定方法

~/.config/direnv/direnvrc に以下の内容を設定。

ALIASES_DIR=".direnv/aliases"

export_function() {
  local name=$1
  local alias_dir=$PWD/${ALIASES_DIR}
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  local target="$alias_dir/$name"
  if declare -f "$name" >/dev/null; then
    echo "#!${SHELL}" > "$target"
    declare -f "$name" >> "$target" 2>/dev/null
    echo "$name" '"$@"' >> "$target"
    chmod +x "$target"
  fi
}

clear_direnv_aliases() {
  local alias_dir=$PWD/${ALIASES_DIR}
  rm -rf $alias_dir/*
}

.envrc はこんな感じ。

export DOCKER_UID=$(id -u)
export DOCKER_GID=$(id -g)

clear_direnv_aliases

php() {
  docker-compose run --rm php php "$@"
}
export_function php

やっていること

direnvrc で指定していることは、

  1. .envrcで定義された関数をシェルスクリプトにして、PATHを通して利用できるようにしている
  2. docker-compose.yamlで利用している $DOCKER_UID $DOCKER_GID の定義

参考サイト: https://github.com/direnv/direnv/issues/73

ちょっと黒魔術っぽいので、嫌いな人は普通に自前でスクリプトを用意して、PATHを通せば良い。
自分は中身を理解できたので、このまま利用している。
もともとアイデアが書かれていたIssueにはBash固定だったけど、自分の場合は $SHELL でエイリアス用のスクリプトができるようにしてある。

結果

$ cd path/to/myproject
direnv: loading .envrc
direnv: export +DOCKER_GID +DOCKER_UID ~PATH

$ php -v
PHP 7.3.7 (cli) (built: Jul 12 2019 22:25:55) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.7, Copyright (c) 1998-2018 Zend Technologies

んー、素晴らしい!

おわりに

こんな感じでphpenvとかインストールしなくても、PHPの開発環境を用意することが出来た。
このやり方なら、さまざまなプログラミング言語やコマンドでも応用できるはずなので、しっくりきた方はお試しあれ。