読者です 読者をやめる 読者になる 読者になる

しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

App Service on Linux の Docker Container が改善された話

Azure Web Apps

何と大晦日に App Service on Linux がアップデートされたことが Twitter で流れていました。海の向こうでは正月休みとかいう概念は無いみたいですね。

Nazim 氏とはメールで何回もやり取りしましたが、めっちゃいい人でした。

xdebug 対応はまあいいとして、メインは overlapped recycling です。これまでイメージをアップデートすると、既存のコンテナを削除してから新しく起動していたようで、アップデート中は 500 を返していました。

適当に PHP で HOSTNAME を返すだけのコードを書いて、リクエストを投げて ID が切り替わるのを確認してみました。40x / 50x の時は例外になるので確認できます。

f:id:shiba-yan:20170102205536p:plain

ポータルからイメージを変えても、500 などを返すことなく ID が変わりました。環境変数 HOSTNAME で返ってくるのは、多分 Docker Container の ID です。

調べた範囲だと 1 サイトでの構成はこんな感じです。推測ですけど。

f:id:shiba-yan:20170102225111p:plain:w600

Antares Server は Apache で動いている ILB っぽいです。おそらく App Service チームの自作。そして App と Kudu の IP アドレスは不定なので、使わないようにしましょう。

172.17.0.1 の素性は curl から叩いてみると簡単にわかります。

f:id:shiba-yan:20170102230638p:plain

単純な LB だけではなく、もっといろいろな機能が実装されている感じがします。

ちなみに App Service on Linux で使われている Mono で動作する Kudu やビルトインイメージの Dockerfile などが GitHub で公開されています。

今は /home のマウントがカスタムイメージの時だけ狂うバグがあるので、ここの Dockerfile をそのまま使っても動かすことはできないです。バグとしては認識されているので多分直ります。

バグが直ればカスタムランタイムをもっと柔軟に作れるようになるので待ってます。

2016 年を振り返ってみる

日常

今年は少し大きな変化があったので軽く書いてみたくなりました。大晦日ですし。

フリーランスになった

3/10 に会社を辞めてフリーランスになりました。辞めた次の日には仲の良かった前職のメンバーと北海道にスキーをしに行ってました。3 月でも吹雪になる北海道マジでやばいと思いました。

f:id:shiba-yan:20160312142536j:plain

平日の昼間から海鮮丼食べながら日本酒を飲む生活をしてました。

かずあきさんが働いている間に飲む酒は最高に美味しい。来月ぐらいにはまたスキーしに行きたい。

フリーランスになってからは週に数日というペースですが、一休で改善の手伝いをしています。最近は ASP.NET Core と Docker で書いたものを本番に乗せたり、クラウド移行のためにいろいろとやってます。

6 回目の Microsoft MVP

前々職の時に受賞した気がするので、結構長い間貰い続けてるなという感じがしてきました。

f:id:shiba-yan:20160407161421j:plain

Azure MVP になりたいと書いて出したのに ASP.NET/IIS のままだったのは今の疑問です。

dotnetConf の日本版で喋った

チャックさんに「dotnetConf Japan 必要なんじゃないっすかー?」みたいなことを言ってたら開催していました。確か ASP.NET Core 1.0 についてアロハを着て話したはずです。

懇親会が過去最大級だったので、もう少しで食べ過ぎて死ぬところでした。まさかケーキもあるとは…。

f:id:shiba-yan:20160709193811j:plain

余ってたので .NET Foundation の部分を丸ごと貰って食べました。

この数か月後の MVP Global Summit で .NET Foundation の Challenge Coin を貰ったのでフラグだったのかもしれません。適当なことを書いている自信はあります。

GERONEKO 大ブーム到来

Xbox 360 を pnop 社に寄贈していたのを思い出して、飲みに行ったついでに GERONEKO を購入して延々と遊んでいました。FUR 300 の壁が高くて非常に苦労しました。

f:id:shiba-yan:20160709235249j:plain

スマホゲーにしたらめっちゃ売れるのではないかと思いました。タッチ難しそうだけど。

3 年振りに MVP Global Summit へ参加

これまでは前職の社員旅行が 10 月末にあったので参加できていなかった Global Summit ですが、フリーランスになったので本当に久しぶりに参加できました。

とりあえず食事が合わなくて辛かった記憶しかないです。

f:id:shiba-yan:20161117163933j:plain

最後の方はコロンビアセンターに登ったりして、少し時間を潰してみたりしました。

振り返りのまとめ

例年通り、このブログで一番読まれたエントリを Google Analytics を使って集計してみました。

  1. 接続文字列の書き方をまとめてみる
  2. Windows 10 に対応した Boot Camp 6 がリリースされたのでインストールしてみた
  3. IIS 7 以降でのアプリケーションプールと権限について調べた
  4. Android TV を搭載した 4K BRAVIA を買ってみた
  5. Entity Framework の俺的まとめ
  6. 接続文字列の書き方をまとめてみる(2014 年版)
  7. Web API よりも HttpClient に注目したい
  8. 格安航空会社 (LCC) に乗りまくった感想
  9. Raspberry Pi 2 に Raspbian を入れた時にやっておいた方が良いことをまとめた
  10. iPhone 6 から iPhone 7 Plus に機種変してみた

そろそろ接続文字列の書き方を覚えてもいいころなのでは…。ちなみに今年書いたエントリは技術的要素ゼロでした、本当にありがとうございました。

全く関係ないですが、今日はコミケに行って高捷少女の画集を買ってきました。

f:id:shiba-yan:20161231160953j:plain:w450

来年こそは台湾へ久し振りに遊びに行きたいと思いました。

App Service on Linux のカスタム Docker イメージ機能を使って nginx + php-fpm な環境を作る

Azure Web Apps PHP

最近は Windows Containers じゃない Docker Container を弄っていたので、勢いで App Service on Linux 向けに nginx + php-fpm という鉄板な構成でカスタムランタイムを作成しました。

既に shibayan/nginx-php-fpm というイメージ名で Docker Hub に上げてあるので、それを使うとコンテンツをディレクトリにコピーするだけの Dockerfile を作れば動きます。

FROM shibayan/nginx-php-fpm

COPY index.php /var/www/html/index.php

index.php にはお馴染みの phpinfo だけ書いておきました。

この Dockerfile をビルドして Docker Hub にプッシュし、App Service で設定すれば終わりです。

f:id:shiba-yan:20161224203205p:plain

実際に作成したイメージをデプロイしました。Server API が FPM になっているのが確認できました。

f:id:shiba-yan:20161224203605p:plain

これだけだと一瞬で終わってしまったので、App Service on Linux について最近調べていたことを簡単にまとめておこうかと思いました。後は作成したイメージについてもう少し説明を書きます。

アーキテクチャについて

そういえば App Service on Linux が Docker Container に対応した話は書いてなかった気がします。アーキテクチャについては公式情報がゼロですが、以下の記事がまとまっていると思います。

Nazim 氏がコメントを書き込んでいるので、大体当たりのようです。軽く基本的な情報をまとめます。

  • ホスト OS は Ubuntu 16.04
  • ビルトインイメージは Debian 8 ベース (debian:jessie)
  • www と scm は別のコンテナで動作している
    • ランタイムに .NET Core を指定しても Kudu で dotnet コマンドが叩けない理由がこれ
  • /home は www と scm 共通でマウントされている

OS が Ubuntu と Debian のどちらかという話がありましたが、両方というのが正解。他にも今は Docker のイメージを変更すると 503 になったりしますが、今後アップデートで対応されるとかなんとか。

docker コマンドを Kudu から見えるようにすると、コンテナ間のアイソレーションで問題になりそうなので、カスタムデプロイスクリプトで docker build というのは非常に難しそうです。

カスタムイメージを作る

アーキテクチャの話はこれぐらいにして、実際に nginx と php-fpm を使う Docker イメージを作成してみます。調べると良く出てくるのが nginx と php-fpm を別コンテナにする方法ですが、App Service on Linux では Docker Compose は使えないので 1 つのコンテナで両方動かすことにします。

ベースとなるイメージは公式の php-fpm を使いました。確か Debian ベースです。

FROM php:7.0.6-fpm

# Install nginx
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
    && echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y nginx --no-install-recommends

# Install PHP extensions
RUN apt-get update \
    && apt-get install -y libpng12-dev \
         libjpeg-dev \
         libpq-dev \
         libmcrypt-dev \
         libldap2-dev \
         libldb-dev \
         libicu-dev \
         libgmp-dev \
    && ln -s /usr/lib/x86_64-linux-gnu/libldap.so /usr/lib/libldap.so \
    && ln -s /usr/lib/x86_64-linux-gnu/liblber.so /usr/lib/liblber.so \
    && ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h \
    && rm -rf /var/lib/apt/lists/* \
    && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \
    && docker-php-ext-install gd \
         mysqli \
         opcache \
         pdo \
         pdo_mysql \
         pdo_pgsql \
         pgsql \
         ldap \
         intl \
         mcrypt \
         gmp \
         zip \
         bcmath \
         mbstring \
         pcntl

# Install Supervisor
RUN apt-get update \
    && apt-get install -y supervisor \
    && mkdir -p /var/log/supervisor

# Add configuration
COPY default.conf /etc/nginx/conf.d/default.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 80

CMD ["/usr/bin/supervisord"]

ダラダラと長いですが、やっていることは nginx / php extensions / supervisor のインストールと設定ファイルのコピーだけです。PHP Extension のインストールは公式の Dockerfile を参考にしました。

nginx の設定ファイルは非常にシンプルです。やっていることは FastCGI の設定と REMOTE_ADDR を正しくするための設定ぐらいです。ちゃんと 80 番ポートをリッスンするようにしておきます。

server {
    listen 80;
    server_name _;
    root /var/www/html;
    index index.php index.html index.htm;
    charset utf-8;

    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.17.0.0/16;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

公式の php-fpm イメージをベースに作っているので、9000 番ポートに FastCGI のリクエストを流し込みます。この辺りは特に代わり映えのしない、ありがちな設定です。

最後に Supervisor の設定ファイルです。nginx と php-fpm を立ち上げているだけです。

[supervisord]
nodaemon=true

[program:php-fpm]
command=php-fpm
priority=10

[program:nginx]
command=nginx -g "daemon off;"
priority=5

とりあえず優先順位をつけて php-fpm が先に起動するようにしました。これで docker build すると nginx と php-fpm のベースイメージが完成するので、あとはコンテンツを追加したイメージを作ります。

本来なら App Service のビルトインイメージと同じように /home/site/wwwroot のファイルを使う方法もありますが、今はちょっとしたバグがあるので紹介は止めておきました。直ったら書きます。