4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Dockerを使ってcomposerをHHVMで動かす

Last updated at Posted at 2018-03-11

TL;DR

  • brewのcomposerはcomposer.pharではないのでhhvm /usr/local/bin/composerしてもPHPで動いてしまう
  • コンテナ上にHHVMとcomposerを用意して解決したので、Dockerfileとその使い方を公開します

動作環境

  • macOS High Sierra(version 10.13.3)
  • Docker Community Edition(version 18.03.0-ce-rc1-mac54)

経緯

PHPerKaigi 2018Hackの話を聞いて触発されてHackを触ってみたものの、hhvm/hhvm-autoloadをインストールしようとすると、HHVMで実行してるのにもかかわらず「HHVMで動かせ」って怒られてしまいました。

$ which composer
/usr/local/bin/composer

$ hhvm /usr/local/bin/composer require hhvm/hhvm-autoload
Using version ^1.6 for hhvm/hhvm-autoload
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - hhvm/hhvm-autoload v1.6.2 requires hhvm ^3.23 -> you are running this with PHP and not HHVM.
    - hhvm/hhvm-autoload v1.6.1 requires hhvm ^3.23 -> you are running this with PHP and not HHVM.
    - hhvm/hhvm-autoload v1.6.0 requires hhvm ^3.23 -> you are running this with PHP and not HHVM.
    - Installation request for hhvm/hhvm-autoload ^1.6 -> satisfiable by hhvm/hhvm-autoload[v1.6.0, v1.6.1, v1.6.2].


Installation failed, reverting ./composer.json to its original content.

原因

このcomposerはbrew install composerでインストールしたものなので、/usr/local/bin/composercomposer.pharとは別物のようです。

$ cat /usr/local/bin/composer
#!/usr/bin/env php
<?php
array_shift($argv);
$arg_string = implode(' ', array_map('escapeshellarg', $argv));
$arg_prefix = preg_match('/--(no-)?ansi/', $arg_string) ? '' : '--ansi ';
$arg_string = $arg_prefix . $arg_string;
passthru("/usr/bin/env php -d allow_url_fopen=On -d detect_unicode=Off /usr/local/Cellar/composer/1.6.3/libexec/composer.phar $arg_string", $return_var);
exit($return_var);

Cellarの中にあるcomposer.pharをHHVMで実行して解決することもできそうですが、なるべく触りたく無い(個人の感想)のでDocker環境を用意することにしました。

できたもの

Dockerfile
FROM hhvm/hhvm

## get composer from composer official image
COPY --from=composer /usr/bin/composer /usr/local/bin/composer

## create non-root user
ARG PUID=1000
ARG PGID=1000

RUN groupadd -g ${PGID} docker && \
  useradd -u ${PUID} -g docker -m docker

## use non-root user
USER docker

# --------------------------------------------------
# additional composer settings
# --------------------------------------------------

ARG USE_PACKAGIST_JP=false
RUN if [ ${USE_PACKAGIST_JP} = true ]; then \
  hhvm /usr/local/bin/composer config -g repos.packagist composer https://packagist.jp \
  ;fi

ARG INSTALL_PRESTISSIMO=false
RUN if [ ${INSTALL_PRESTISSIMO} = true ]; then \
  hhvm /usr/local/bin/composer global require hirak/prestissimo \
  ;fi

# --------------------------------------------------
# final touches
# --------------------------------------------------

WORKDIR /app

## set -d option to control "SlowTimer" warning
ENTRYPOINT [ "hhvm", "-d", "hhvm.http.slow_query_threshold=30000", "/usr/local/bin/composer" ]

CMD [ "--help" ]

ライセンスは放棄しますので、ご自由にお使いください。

解説

ベースイメージ

FROM hhvm/hhvm

ベースイメージはhhvm/hhvm(ubuntu 14.04ベース)です。450MBほどあります。multi-stage buildsを利用すればalpineやbusyboxをベースイメージとして作れるのでは?と思って試行錯誤したのですがうまくいかず、時間の無駄だと判断してやめました。

composerを持ってくる

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

composerはオフィシャルのイメージからもらってきています。/usr/bin/composerとpathを決め打ちしているのが気になりますが見なかったことにします。multi-stage buildsは便利ですね。

参考

ルート権限のないユーザを用意する

ARG PUID=1000
ARG PGID=1000

RUN groupadd -g ${PGID} docker && useradd -u ${PUID} -g docker -m docker

USER docker

composerはroot権限を持ったユーザで実行すると怒られるので、適当なユーザを用意しています。

composerの設定をする

ARG USE_PACKAGIST_JP=false
RUN if [ ${USE_PACKAGIST_JP} = true ]; then \
  hhvm /usr/local/bin/composer config -g repos.packagist composer https://packagist.jp \
  ;fi

ARG INSTALL_PRESTISSIMO=false
RUN if [ ${INSTALL_PRESTISSIMO} = true ]; then \
  hhvm /usr/local/bin/composer global require hirak/prestissimo \
  ;fi

このあたりは趣味です。なのでデフォルトではインストールしたりしないようにしています。
インストールしたい方は、イメージをビルドするときに--build-argオプションで変えてください。(後述)

参考

残り

WORKDIR /app

ENTRYPOINT [ "hhvm", "-d", "hhvm.http.slow_query_threshold=30000", "/usr/local/bin/composer" ]

CMD [ "--help" ]

コンテナを起動するときにワーキングディレクトリにcomposer.jsonのあるディレクトリをマウントすることで、コンテナの中で実行したcomposerの成果物がホスト側に反映されます。

エントリーポイントでは、composerをHHVMで実行すると発生する「SlowTimer」を抑制するためのオプションをつけています。

参考

使い方

イメージをビルドする

とりあえずビルドするならこのコマンドを打ってください。

docker build -t hh-composer /path/to/Dockerfile

オプション

--build-argオプションで変えられます。

  • USE_PACKAGIST_JP=true|false - packagist.jpを参照するようにするかどうか。デフォルトはfalse
  • INSTALL_PRESTISSIMO=true|false - composerを早くするプラグイン(hirak/prestissimo)をインストールするかどうか。デフォルトはfalse

設定例

packagist.jpを使い、hirak/prestissimoをインストールする場合。

docker build --build-arg USE_PACKAGIST_JP=true --build-arg INSTALL_PRESTISSIMO=true -t hh-composer /path/to/Dockerfile

変更する数だけ--build-argオプションを書かないといけないのは少し面倒くさいですね。

コンテナを起動してcomposerを実行する

// 長いオプションだとこう
docker run --rm --tty --interactive --volume $(pwd):/app hh-composer

// 短いオプションだとこう
docker run --rm -it -v $(pwd):/app hh-composer

hh-composerに何も引数を付けないと、--helpが呼ばれるようになってます。

それでは、当初の目的であったhhvm/hhvm-autoloadをインストールしてみます。

$ docker run --rm -it -v $(pwd):/app hh-composer require hhvm/hhvm-autoload
Using version ^1.6 for hhvm/hhvm-autoload
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
  - Installing fredemmott/hack-error-suppressor (v1.0.1): Downloading (100%)
  - Installing hhvm/hhvm-autoload (v1.6.2): Downloading (100%)
Writing lock file
Generating autoload files

いい感じですね:yum:

使いやすくする

いちいち長いコマンドを打つのはめんどくさいので、shellの設定ファイル(.bashrc .zshrcなど)に関数を追加します。

hh-composer () {
  tty=
  tty -s && tty=--tty
  docker run \
    $tty \
    --interactive \
    --rm \
    --volume $(pwd):/app \
    hh-composer "$@"
}

これでhh-composerとして実行することができるようになります:tada:

$ hh-composer --version
Composer version 1.6.3 2018-01-31 16:28:17

参考

注意点

  • composerとHHVMはコンテナ上で動いていて、コマンド実行後すぐに破棄されてしまうため、composer global installしたい場合はDockerfileをいじるしかありません
  • composerとHHVMのバージョンがコンテナ側とホスト側で一致してないことでエラーが起きる可能性があります
  • 一部のpackageはインストール時にscriptを実行しますが、それが反映されるのはコンテナ側になります。それによって問題が起きる可能性があります

最後に

誤字脱字、内容の間違いなどは編集リクエスト、コメント、Twitter(@shuymn)など何らかの方法で教えていただければと思います。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?