はじめに
docker-swarmとか全く知らないdocker素人です。
Proxy環境でdockerの仮想環境を作ったらapt-getが通らなくて無事死亡したので調べてみました。
あ、一つ言っておきますが、ネットワークの知識はほぼありません。
ProxyとDNSがどういう機能・役割であるかはわかりますが、どのように連携してシステムになってるのかすら知りません。
前編(?):Dockerで開発環境を仮想化する
Docker DaemonにProxy設定を教える
dockerコマンドを実行するときは外部のネットワークに接続する必要があるならDocker Daemon自体にプロキシ設定が必要です。
たとえば、Docker DaemonがProxy設定を知らないと、FROMコマンドでイメージをDLしてくることができないと思います。
Proxy設定には以下の5種類ぐらいがあると思いますが、必要なのは赤色の設定だけみたいです。
Dockerが大文字設定を見るのか、小文字設定を見るのか知らないので両方定義していきます。
- NO_PROXY
- HTTP_PROXY
- HTTPS_PROXY
- SOCK_PROXY
- FTP_PROXY
upstartの人
export no_proxy='export no_proxy=127.0.0.1,localhost,xxx.xxx.xxx.xxx'
export NO_PROXY="${no_proxy}"
export http_proxy='http://your.proxy.url:port/'
export HTTP_PROXY="${http_proxy}"
export https_proxy='https://your.proxy.url:port/'
export HTTPS_PROXY="${https_proxy}"
$ sudo service docker restart
Systemdの人
[Service]
Environment="HTTP_PROXY=http://your.proxy.url:port/" "HTTPS_PROXY=https://your.proxy.url:port/"
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
確認する
docker info
コマンドを使って最後辺りに表示されているハズです。
$ docker info
... ... ...
... ...
HTTP_PROXY: http://your.proxy.url:port/
HTTPS_PROXY:https://your.proxy.url:port/
NO_PROXY: 127.0.0.1,localhost,xxx.xxx.xxx.xxx'
....
もし、次のエラーメッセージが表示されたら
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: proxyconnect tcp: tls: oversized record received with length 20527.
See 'docker run --help'.
このエラーの詳細な原因は正直分かっていません。
だが、HTTPSでエラーを吐いているのでHTTPでアクセスしたら?という乱暴な発想でProxy設定を変えてみたら繋がりました。
docker info
コマンドで以下の出力になるように、今までのdockerの設定を変えてください。
$ docker info
... ... ...
... ...
HTTP_PROXY: http://your.proxy.url:port/
HTTPS_PROXY:http://your.proxy.url:port/
NO_PROXY: 127.0.0.1,localhost,xxx.xxx.xxx.xxx'
....
……本当にいいのか?
現状のDocker Containerの問題点
Docker DaemonにProxy設定を教えたことで、FROMコマンドを使ってイメージをDLすることができたと思います。
しかし、Container側でapt-getなど、インターネットに接続する必要があるコマンドを使う場合はおそらく通りません。
以下の2点を設定したら繋がりました。
- DNS設定
- Proxy環境変数
Docker ContainerにDNS設定を教える
私の環境ではDNSサーバーが自前に用意されている環境でした。
つまり、そのDNSサーバーにProxyサーバーの名前解決を依頼しているネットワークです。(多分。。。詳しくは知りません)
なので、Proxyサーバーの設定云々の前にDNSサーバーの所在をDocker Container側に教えてあげる必要があります。
方法1:コマンドオプションで渡す
dockerのrunコマンド時に設定できます。
$ docker run --dns xxx.xxx.xxx.xxx (略)
でも、デスクトップPCとか持ち運ばない系の作業環境だと毎回入力するのメンドウですよね
※デスクトップだからといって、テストサーバーと本番サーバーとかProxyの設定が変わるようなお仕事では注意が必要。
方法2:デフォルト設定に加える
upstartの人
DOCKER_OPTS="--dns xxx.xxx.xxx.xxx"
$ sudo service docker restart
Systemdの人
なんか、実験環境のSystemdは/etc/systemd/system/multi_user/docker.service
になっていました。
結局、シンボリックリンクで/lib/docker.d/docker.conf
かなんかに飛ぶんだけど。
以下のパスで見つからない人は、find
コマンドかなんかで探してみてください。
[Service]
Environment="HTTP_PROXY~" "HTTPS_PROXY~" "DOCKER_NETWORK_OPTIONS=--dns xxx.xx.xxx.xxx"
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_NETWORK_OPTIONS
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
Docker ContainerにProxy設定を教える
# 仮想化するベースOS
FROM ubuntu:14.04
########## ROOT WORKS ##########
# Proxy設定
ENV ftp_proxy 'ftp://your.porxy.url:port'
ENV http_proxy 'http://your.porxy.url:port'
ENV https_proxy 'https://your.proxy.url:port'
ENV socks_proxy 'socks://your.proxy.url:port'
ENV no_proxy '127.0.0.1,localhost,xxx.xxx.xxx.xxx'
# 一般ユーザーを追加
RUN :ユーザーアカウント追加 \
&& useradd -m tester \
&& :sudo権限を付与 \
&& gpasswd -a tester sudo \
&& :パスワード設定 \
&& echo "tester:test_pass" | chpasswd
# ディレクトリの移動
WORKDIR /home/tester
# apt-get
RUN apt-get update \
&& apt-get install -y build-essential
########## USER WORKS ##########
# 以降のRUN/CMDを実行するユーザー
USER tester
Dockerfileに環境変数として設定してみたんですが、何故かapt-getコマンドが動きませんでした。
Something wicked happened resolving 'your.proxy.co.jp:http'
DNSサーバーも設定しましたし、Proxyサーバーの名前解決が出来ないのは正直分かりません。
適当にrootユーザーではapt-getを実行してみると繋がりました。
環境変数もしくはホスト側のresolveを追加したユーザーで参照できていない、とか?
apt-get用の設定
apt-getコマンドが処理時に参照するapt.confを設定することで通りました。
apt-getは解決できても他のコマンドで外へ行くことができないのではないかと思いますが。
Acquire::http:proxy "http://your.proxy.url:port"
Acquire::https:proxy "https://your.proxy.url:port"
Acquire::ftp:proxy "ftp://your.proxy.url:port"
Acquire::socks:proxy "socks://your.proxy.url:port"
apt-get解決時は上記のファイルを見るらしいので、このファイルを自動生成させます。
すでに存在するファイルをADDやCOPYでコンテナ側へ持って行ってもいいと思います。
(略)
# Proxy設定
ENV ftp_proxy 'ftp://your.porxy.url:port'
ENV http_proxy 'http://your.porxy.url:port'
ENV https_proxy 'https://your.proxy.url:port'
ENV socks_proxy 'socks://your.proxy.url:port'
ENV no_proxy '127.0.0.1,localhost,xxx.xxx.xxx.xxx'
RUN : "apt-getコマンドに対するProxy設定" \
&& { \
echo 'Acquire::http:proxy "'${ftp_proxy}'";'; \
echo 'Acquire::https:proxy "'${http_proxy}'";'; \
echo 'Acquire::ftp:proxy "'${ftp_proxy}'";'; \
echo 'Acquire::socks:proxy "'${socks_proxy}'";'; \
} | tee /etc/apt/apt.conf
(略)
echoした内容をファイルをリダイレクトしているだけなので難しくはありませんね。
一応、環境変数とapt.confなどの組み合わせは確かめてみました。
\ | 何もしない | 環境変数 | apt.conf |
---|---|---|---|
root | ○ | ○ | ○ |
user | × | × | ○ |
おわり
いろいろとDockerには落とし穴だったりがあるようですが、さすがに流行っているソフトウェアなだけあって情報は多いです。
頑張って使っていきましょう!!
あと、Dockerfileはhadolintを使ってチェックしてあげてくださいね。