docker-composeでのプロキシ設定を一つのファイルにまとめる

docker-composeでのプロキシ設定を一つのファイル(`.env`というファイル)にまとめたリポジトリを作りました。

[SolKul/docker-compose-proxy](https://github.com/SolKul/docker-compose-proxy)

**2021/3/15追記
docker-composeの.envファイルの認識場所が変わったようです。今度からは`docker-compose.yml`と同じ階層に保存してください。特にVSCodeのRemote Containerで.envファイルを使っている人は注意が必要です**
[docker-composeの.envファイルの認識場所が変わった](https://qiita.com/SolKul/items/034cd6cc3bae5a2f5146)


# メリット
このようにするメリットとしては、

- プロキシ設定がimageに焼き付かない
- 別の人に使って貰おうと`docker-compose.yml`を配布したいと思ったが、プロキシ設定に認証情報が入っているため配布したくない場合でも、この方法を使えば、`docker-compose.yml`にはプロキシ設定が記されておらず、`.env`ファイルの中身だけ変えればいいので、配布しやすい

などがあります。

# 解説
## 前提知識

前提知識としてそもそもプロキシサーバの概要や役割、
Linuxの環境変数、プロキシの設定方法、
Dockerfileの仕組みについて知っておいたほうがいいでしょう。

[Docker入門（第四回）～Dockerfileについて～ | さくらのナレッジ](https://knowledge.sakura.ad.jp/15253/)

最悪、リポジトリをコピペしても動くとは思いますが、こうした知識がないとトラブルやエラーが起きた場合に対処できなく積んでしまうと思います。

## Linuxの各種コマンドでプロキシを使うには

プロキシについて調べていくといろんな設定ファイルをいじらなければいけないように感じますが、
基本的に以下の環境変数を設定していればプロキシを使えます。

```
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
```

`NO_PROXY`、`no_proxy`以外の環境変数にプロキシの
`http://<user>:<password>@<your-proxy>:<proxy-port>/`
(認証付きでない場合は`<user>:<password>@`を外す。)
を設定すれば大丈夫です。

`no_proxy`には`127.0.0.1`,`localhost`などを設定すればいいと思います。


## Dockerfile、docker-composeでのプロキシ設定

Dockerfile、docker-composeでのプロキシ設定についてはこの記事が詳しいです。

[防火壁の中の Docker](https://qiita.com/jeffi7/items/3e40c59744b5801fd40a)

またこの記事を理解するにはDockerfileのARGやENVの知識、`docker-compose.yml`の`environment:`についての知識を知っておいたほうがいいでしょう。
[ARG | Dockerfile reference](https://docs.docker.com/engine/reference/builder/#arg)
[Dockerドキュメント | compose中の環境変数](https://docs.docker.com/compose/environment-variables/)

まとめると、Dockerfileのビルド変数(build-arg)にプロキシの設定を渡すことで、**イメージのビルド中のプロキシ設定**が設定され、`docker-compose.yml`の`environment:`を設定することで、**立ち上がったコンテナのプロキシ設定**が設定できます。

プロキシに関するビルド変数は予め宣言されている(predefined)なので、
Dockerfile内で`ARG HTTP_PROXY`とする必要はありません。

([Predefined ARGs](https://docs.docker.com/engine/reference/builder/#predefined-args)参照)

## .envファイルについて

そして更に、このリポジトリではdocker-compose中のデフォルトの環境変数を設定するために、`.env`ファイルを使っています。

docker-compose中で環境変数の使い方や`.env`ファイルについてはこの記事や公式リファレンスを参考にしてください

[docker-composeのenv_fileと.envファイルの違い](https://qiita.com/SolKul/items/989727aeeafcae28ecf7
)
[Dockerドキュメント | compose中の環境変数](https://docs.docker.com/compose/environment-variables/)

.envファイルを使うことで、`docker-compose up`した際に、以下の`docker-compose.yml`の$から始まる環境変数に.envファイルに記したプロキシ設定が代入されます。
また、そのホストに別のプロキシが設定されていれば、そのホストのプロキシ設定が代入され、.envファイルの値は使われません。

```docker-compose.yml
version: '3'

services:
  test:
    build:
      context: .
      # ビルド中にプロキシを使うための設定
      args:
        - HTTP_PROXY=$HTTP_PROXY
        - http_proxy=$http_proxy
        - HTTPS_PROXY=$HTTPS_PROXY
        - https_proxy=$https_proxy
        - FTP_PROXY=$FTP_PROXY
        - ftp_proxy=$ftp_proxy
        - NO_PROXY=$NO_PROXY
        - no_proxy=$no_proxy
    # 立ち上がったコンテナでプロキシを使うための設定
    environment:
      - HTTP_PROXY=$HTTP_PROXY
      - http_proxy=$http_proxy
      - HTTPS_PROXY=$HTTPS_PROXY
      - https_proxy=$https_proxy
      - FTP_PROXY=$FTP_PROXY
      - ftp_proxy=$ftp_proxy
      - NO_PROXY=$NO_PROXY
      - no_proxy=$no_proxy
```


```yaml:.env
HTTP_PROXY=proxy_url:port
http_proxy=proxy_url:port
HTTPS_PROXY=proxy_url:port
https_proxy=proxy_url:port
FTP_PROXY=proxy_url:port
ftp_proxy=proxy_url:port
NO_PROXY=no_proxy_url
no_proxy=no_proxy_url
```

この状態で、`docker-compose up`を実行し、次のコマンドなどで、コンテナ内でbashを実行すれば`proxy`が設定されていることが確認できると思います。

```bash
$ docker-compose exec ${サービス名(今回の場合test)} bash  
root $ env | grep PROXY
### ここに設定したプロキシが表示される ###
```

## 注意

### 認証について

プロキシへの認証にユーザー名、パスワードではなくホストの持つ証明書を用いている場合があります。立ち上げたコンテナは何ら有効な認証情報を持っていないのでそのままではコンテナはプロキシにアクセスできません。その場合、１度ホストがプロキシにアクセスしプロキシサーバに認証してもらうと、コンテナもプロキシに接続できることがあります。

### `.env`ファイルの配置場所

~~`.env`ファイルは**`docker-compose`コマンドを実行したときのディレクトリにある必要があります(ワーキングディレクトリ)**
他の場所では認識しません。~~

~~例えばVSCodeのRemote Containerでは`docker-compose`をVSCodeのルートディレクトリで実行しているので
`.env`ファイルは今VSCodeが開いているルートディレクトリに置かないと、正常に動作しません。~~

**2021/3/15追記
docker-composeの.envファイルの認識場所が変わったようです。今度からは`docker-compose.yml`と同じ階層に保存してください。**
[docker-composeの.envファイルの認識場所が変わった](https://qiita.com/SolKul/items/034cd6cc3bae5a2f5146)


# 参考:Qiitaのdockerプロキシ記事まとめ

Linux環境の場合:

- [防火壁の中の Docker](https://qiita.com/jeffi7/items/3e40c59744b5801fd40a)

この記事でほぼ網羅されていますが、
Windowsの場合、Docker Desktop for Windowsで追加の設定をしないとdocker pullができません
次の記事を見て設定してください。

- [Proxy環境下でDocker for Windowsを使う](https://qiita.com/wryun0suke/items/1f4bbd2977ae41ee7a36)