HHVM構築
ひと昔前はHHVMを用意するのにも大変な時代がありましたが、
現在はDockerを利用して簡単に構築することができます。
今回は一からHHVM開発環境を作成してみましょう!
HHVMのコンテナ自体はDocker Hubにて公式が公開しています。
本番運用などを考えると、fastcgiで動かすメリットはあまりありません。
proxygenを利用することで、HHVM自体の管理機能やパフォーマンス面でもアドバンテージがあります。
(実際のコンテナ運用ライクな内容は別で紹介します。)
GCP/AWSなどで運用する場合はhhvm-proxygen単体でも十分ですが、
今回はNginxをフロントに置き、upstreamでhhvm-proxygenに流す構成にします。
(log収集などもそちらの方が楽でしょう!)
HHVM container
まずはhhvm/hhvm-proxygen:latestを利用します。
FROM hhvm/hhvm-proxygen:latest AS dev
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive
RUN apt install -y dnsutils iputils-ping net-tools
RUN hhvm --version && php --version
RUN cd $(mktemp -d) \
&& curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
hhvmはUbuntuで動作する様になっているため、alpineなどの提供はありません。
そのため、サイズはちょっとデカめです。
次にHHVMのphp.iniを用意します。
date.timezone = Asia/Tokyo
hhvm.log.header = true
hhvm.debug.server_error_message = true
display_errors = On
html_errors = On
error_reporting = 22527
hhvm.server.fix_path_info = true
hhvm.server.type = proxygen
hhvm.server.port = 18080
hhvm.log.use_log_file = true
hhvm.server.source_root = /var/www/public
hhvm.php_file.extensions[hack]=1
hhvm.jit=1
hhvm.server.default_document = "index.hack"
hhvm.server.error_document404 = "index.hack"
hhvm.server.utf8ize_replace=true
hhvm.log.file=/dev/stderr
hhvm.admin_server.port=19001
hhvm.admin_server.password=SomePassword
ここで重要なのは、hhvm.server.source_root
です。
proxygenを使ってHackをアプリケーションサーバとして動かすため、
Hackのエントリポイントになるファイルが設置してあるディレクトリを指定します。
エントリポイントのファイルはhhvm.server.default_document
で指定します。
hhvm.server.port
はproxygenを通信させるポートです。
またHHVMの監視やプロセスの管理などは
HHVMで用意されているAdmin Serverを利用した方が便利です。
これを利用するためにhhvm.admin_server.port
、hhvm.admin_server.password
を記述します。
当然コンテナを利用しますので、logはhhvm.log.file=/dev/stderr
とします。
Nginx container
nginxはalpineなどの軽量なものを利用しましょう。
先にconfを用意しておきましょう。
upstream hhvm-proxygen {
server hhvm:18080;
keepalive 300;
}
server {
listen 80;
server_name _;
charset utf-8;
location / {
proxy_pass http://hhvm-proxygen;
proxy_http_version 1.1;
proxy_set_header Connection "";
send_timeout 180;
proxy_connect_timeout 300;
proxy_read_timeout 300;
proxy_send_timeout 300;
}
}
hhvm-proxygenコンテナの名前をhhvmとして記述しています。
AWS Fargateなどで動かす場合は適宜変更してください。
nginx.confもコンテナ運用しやすい様にログフォーマットなどを変更しておきましょう。
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format json escape=json '{'
'"time": "$time_local",'
'"remote_addr": "$remote_addr",'
'"host": "$host",'
'"remote_user": "$remote_user",'
'"status": "$status",'
'"server_protocol": "$server_protocol",'
'"request_method": "$request_method",'
'"request_uri": "$request_uri",'
'"request": "$request",'
'"body_bytes_sent": "$body_bytes_sent",'
'"request_time": "$request_time",'
'"upstream_response_time": "$upstream_response_time",'
'"http_referer": "$http_referer", '
'"http_user_agent": "$http_user_agent",'
'"http_x_forwarded_for": "$http_x_forwarded_for",'
'"http_x_forwarded_proto": "$http_x_forwarded_proto"'
'}';
access_log /dev/stdout json;
error_log /dev/stderr warn;
sendfile on;
keepalive_timeout 65;
gzip off;
proxy_buffering off;
proxy_cache off;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
include /etc/nginx/conf.d/*.conf;
}
これでログ収集などに対応しやすくなるでしょう!
nginx自体はここではnginx:1.19-alpine
を利用します。
FROM nginx:1.19-alpine
RUN apk --update add tzdata && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
apk del tzdata && \
rm -rf /var/cache/apk/*
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
RUN echo "Not Found" > /usr/share/nginx/html/index.html
COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf
COPY docker/nginx/conf.d/ /etc/nginx/conf.d/
最低限のものだけやっておきます。
これでコンテナの準備ができました。
Docker Compose
次にdocker-compose.ymlを用意しておきます。
version: '3.8'
services:
hhvm:
build:
context: .
dockerfile: ./docker/hhvm/Dockerfile
volumes:
- .:/var/www
- ./docker/hhvm/hh.conf:/etc/hh.conf
- ./docker/hhvm/php.ini:/etc/hhvm/php.ini
command: hhvm --mode server -vServer.AllowRunAsRoot=1
tty: true
container_name: hhvm
ports:
- 19001:19001
restart: always
web-server:
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
ports:
- 80:80
container_name: web-server
tty: true
特筆すべき点は特にありませんが、ここで指定している19001
は、管理用のAdmin Serverになりますので、
実際に運用する場合は内部通信のみ許可をするなどインターネットには公開しない様にしましょう。
hhvm-proxygenは外部に許可せず、Nginxのみと通信するようにしています。
NginxやApache HTTP Serverを置かない場合はhhvm-proxygenのポートも記述しておきましょう。
Hackを実行する
ここまで用意ができたらhhvm.server.source_root
で指定したディレクトリに、
hhvm.server.default_document
で指定したファイルを作成しておきましょう。
ファイルはindex.hack
としましょう!
use function phpversion;
<<__EntryPoint>>
async function main(): Awaitable<void> {
echo phpversion();
}
エントリポイントとなるファイルにアクセスすると、
<<__EntryPoint>>
Attributeを指定した関数が自動で動く仕組みになっています。
他の言語でおなじみのmain関数と同じ扱いにできる、ということになります。
ファイルを用意したら起動させましょう。
# build
$ docker-compose build --no-cache
# boot
$ docker-compose up -d
起動できたら、http://127.0.0.1/
などにアクセスしてみましょう。
ブラウザなどで下記の出力がされれば問題ありません!
次にAdmin Serverにアクセスしてみましょう。
php.iniで指定したhhvm.admin_server.port
、
hhvm.admin_server.password
を利用します。
設定例ではhttp://127.0.0.1:19001
となりますので、19001にアクセスします。
画面上にたくさんの管理用エンドポイントが表示されていれば設定OKです。
例としてサーバステータスを取得したい場合は、
hhvm.admin_server.password
で指定したパスワードを使ってアクセスします。
アクセスする場合は下記の通りです。
http://127.0.0.1:19001/status.json?auth=SomePassword
HHVMのステータス情報がJSONで表示されます。
これらの情報を用いて実運用などに備えるといいでしょう!
今回は商用で実際にHHVMをコンテナで運用できる様に簡単な設定を紹介しました。
次回をお楽しみに!