【Docker】Docker実行時のログを確認する～private-isuの環境構築でハマった話～

# 初めに
docker-composeで環境構築をしていた際、コンテナがうまく立ち上がりませんでした。
理由を調べるためにログを確認したので、その時のコマンドをアウトプットします。

# 結論
dockerのログを確認するコマンドは`docker logs コンテナ名`になります。
立ち上がってないコンテナのログを調べる場合でもコンテナ名は必須になります（正確には立ち上げようとしたコンテナの名前になりますね）。


# ログ見てみました
せっかくなので、どういう経緯でこのコマンドを利用したのかについてもアウトプットします。

## 背景
皆様、ISUCONをご存じでしょうか？
[ISUCON](https://isucon.net/)とは、LINE株式会社が行っているwebパフォーマンスチューニングコンテストのことです。
あるWebサービスを題材として時間内でチューニングを行い、どのチームが一番パフォーマンスを上げることができるかを競うコンテストになります。

今回は、過去にその大会で使われていた[private-isu](https://github.com/catatsuy/private-isu)というソースを用いてWEBパフォーマンスチューニングを学ぼうとしました。

## 起動させる環境、ソフトウェア
* Windows11
* Docker desktop（4.24.1）
* Docker Engine（v24.0.6）
* nginx（1.24）
* mysql（8.0）
* memcached（1.6）

## Dockerを使ってコンテナで起動させてみる
親切なことに、このソース内に既にdocker-compose.ymlが定義されています。そのためデフォルト設定であれば`docker compose up`コマンドでコンテナを立ち上げることが可能です。コンテナ起動後はlocalhostにアクセスすることでwebサイトを見ることが可能です。

私はデフォルト設定から以下の変更を行いました。
* 使用言語をrubyからphpに変更
* アクセスログ出力フォーマットを変更

### 使用言語をrubyからphpに変更
readmeに沿って`docker-compose.yml`に変更を加えました。
buildの値を`php/`に変更したのみです。
``` docker-compose.yml
  app:
    # Go実装の場合は golang/ PHP実装の場合は php/
    build: php/
    environment:
      ISUCONP_DB_HOST: mysql
      ISUCONP_DB_PORT: 3306
      ISUCONP_DB_USER: root
      ISUCONP_DB_PASSWORD: root
      ISUCONP_DB_NAME: isuconp
      ISUCONP_MEMCACHED_ADDRESS: memcached:11211
    links:
      - mysql
      - memcached
    volumes:
      - ./public:/home/public
    init: true
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1g
```

また、phpを使う場合はnginxのデフォルトのconfファイルではなく、php用に用意されたconfファイルを使用する必要があるみたいです。こちらもreadmeに沿って修正します。
```
cd webapp/etc
mv nginx/conf.d/default.conf nginx/conf.d/default.conf.org
mv nginx/conf.d/php.conf.org nginx/conf.d/php.conf
```


### アクセスログ出力フォーマットを変更
デフォルトのアクセスログだと見づらいため、json形式のログフォーマットに変更しました。
↑で作成した`nginx/conf.d/php.conf`の中に以下を記載します。

```nginx/conf.d/php.con
server {
    # ログフォーマットの設定
    log_format json escape=json '{'
      '"time_local":"$time_local",'
      '"remote_addr":"$remote_addr",'
      '"request_method":"$request_method",'
      '"request_uri":"$request_uri",'
      '"status":$status,'
      '"body_bytes_sent":$body_bytes_sent,'
      '"http_referer":"$http_referer",'
      '"http_user_agent":"$http_user_agent",'
      '"http_x_forwarded_for":"$http_x_forwarded_for",'
      '"request_time":$request_time,'
      '"upstream_response_time":$upstream_response_time,'
      '"upstream_addr":"$upstream_addr",'
      '"upstream_status":$upstream_status'
    '}';

    # 設定したログフォーマットを使うように指定
    access_log /var/log/nginx/access.log json;

    listen 80;

    client_max_body_size 10m;
    root /public;

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

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php {
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_index index.php;
        fastcgi_pass app:9000;
    }
}

```

そのほかにもreadmeに沿って手順を実行しました。

## いざコンテナ作成！
`docker compose up -d`で実際に実行してみます。

```
$ docker compose up -d
[+] Running 5/5
 ✔ Network webapp_default        Created                                                                                                                                                                              0.0s 
 ✔ Container webapp-mysql-1      Started                                                                                                                                                                              0.0s 
 ✔ Container webapp-memcached-1  Started                                                                                                                                                                              0.0s 
 ✔ Container webapp-app-1        Started                                                                                                                                                                              0.0s 
 ✔ Container webapp-nginx-1      Started  
```

無事にコンテナが起動したように見えたのですが、ステータスを確認したところ、`webapp-nginx-1`がありません。

```
$ docker ps
CONTAINER ID   IMAGE           COMMAND                   CREATED              STATUS              PORTS                               NAMES
d6196bc4255d   webapp-app      "docker-php-entrypoi…"   About a minute ago   Up About a minute   9000/tcp                            webapp-app-1
62a9396d09c5   mysql:8.0       "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:3306->3306/tcp, 33060/tcp   webapp-mysql-1
2de9b089c6b1   memcached:1.6   "docker-entrypoint.s…"   About a minute ago   Up About a minute   11211/tcp                           webapp-memcached-1
```

## じゃあログ見てみるか
手順漏れがないかなどしばらく確認していたのですが、一向に解決しません。
そのため、起動時のdockerのログを確認してみることにしました。

```
$ docker logs webapp-nginx-1
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
nginx: [emerg] "log_format" directive is not allowed here in /etc/nginx/conf.d/php.conf:21
```

なんかよくわからんけどlog_formatが認識されてないっぽい。
その辺に当たりをつけて調べてみると、「アクセスログ出力フォーマットを変更」の手順で記述した書き方が間違っていたみたいです。

正しくはこうらしい。
```nginx/conf.d/php.conf
# log_formatはserverの外に定義しないとだめらしい。
log_format json escape=json '{'
  '"time_local":"$time_local",'
  '"remote_addr":"$remote_addr",'
  '"request_method":"$request_method",'
  '"request_uri":"$request_uri",'
  '"status":$status,'
  '"body_bytes_sent":$body_bytes_sent,'
  '"http_referer":"$http_referer",'
  '"http_user_agent":"$http_user_agent",'
  '"http_x_forwarded_for":"$http_x_forwarded_for",'
  '"request_time":$request_time,'
  '"upstream_response_time":$upstream_response_time,'
  '"upstream_addr":"$upstream_addr",'
  '"upstream_status":$upstream_status'
'}';

server {

    # ここは変更なし
    access_log /var/log/nginx/access.log json;

    listen 80;

    client_max_body_size 10m;
    root /public;

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

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php {
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_index index.php;
        fastcgi_pass app:9000;
    }
}

```

## 再実行

修正後、再度実行したところ、ちゃんとコンテナが起動できたことが確認できました。

```
$ docker compose up -d
[+] Running 5/5
 ✔ Network webapp_default        Created   0.0s 
 ✔ Container webapp-memcached-1  Started   0.0s 
 ✔ Container webapp-mysql-1      Started   0.1s 
 ✔ Container webapp-app-1        Started   0.0s 
 ✔ Container webapp-nginx-1      Started   0.0s 
$
$ docker ps      
CONTAINER ID   IMAGE           COMMAND                   CREATED         STATUS         PORTS                               NAMES
4355c5e62cbe   nginx:1.24      "/docker-entrypoint.…"   8 seconds ago   Up 6 seconds   0.0.0.0:80->80/tcp                  webapp-nginx-1
9e58a7987b4e   webapp-app      "docker-php-entrypoi…"   8 seconds ago   Up 7 seconds   9000/tcp                            webapp-app-1
5cd407caa6c3   mysql:8.0       "docker-entrypoint.s…"   8 seconds ago   Up 7 seconds   0.0.0.0:3306->3306/tcp, 33060/tcp   webapp-mysql-1
91d75ff910e1   memcached:1.6   "docker-entrypoint.s…"   8 seconds ago   Up 7 seconds   11211/tcp                           webapp-memcached-1
PS C:\Users\rogto\workspace\isucon\private-isu\webapp> 
```

localhostにアクセスしたところも問題なくサイトが開いてくれました。
![スクリーンショット 2023-10-06 202405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/ff893d94-0dff-b8c7-79e6-d0905ba7cebb.png)


# 最後に
今回はISUCONのソースを用いてdockerのログの確認方法を学びました。
環境構築が済んだので、WEBパフォーマンスチューニングを勉強していきます。
またアウトプットします。

# 参考
* [private-isu](https://github.com/catatsuy/private-isu)
* [Docker環境構築で困ったらログを見る！](https://logical-studio.com/develop/backend/20220311-dockerlogs/)
* [達人が教えるWebパフォーマンスチューニング〜ISUCONから学ぶ高速化の実践](https://gihyo.jp/book/2022/978-4-297-12846-3)