Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
76
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Proxy環境でdockerを外に繋ぐ方法

はじめに

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の人

/etc/default/docker
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}"
docker再起動
$ sudo service docker restart

Systemdの人

/etc/systemd/system/docker.service
[Service]
Environment="HTTP_PROXY=http://your.proxy.url:port/" "HTTPS_PROXY=https://your.proxy.url:port/"
docker再起動
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

確認する

docker infoコマンドを使って最後辺りに表示されているハズです。

dockerの設定確認
$ 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の設定確認
$ 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の人

/etc/default/docker
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コマンドかなんかで探してみてください。

/etc/systemd/system/docker.service.d/docker.conf
[Service]
Environment="HTTP_PROXY~" "HTTPS_PROXY~" "DOCKER_NETWORK_OPTIONS=--dns xxx.xx.xxx.xxx"
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_NETWORK_OPTIONS
docker再起動
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

Docker ContainerにProxy設定を教える

dockerfile
# 仮想化するベース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コマンドが動きませんでした。

aptエラーメッセージ
Something wicked happened resolving 'your.proxy.co.jp:http'

DNSサーバーも設定しましたし、Proxyサーバーの名前解決が出来ないのは正直分かりません。
適当にrootユーザーではapt-getを実行してみると繋がりました。

環境変数もしくはホスト側のresolveを追加したユーザーで参照できていない、とか?

apt-get用の設定

apt-getコマンドが処理時に参照するapt.confを設定することで通りました。
apt-getは解決できても他のコマンドで外へ行くことができないのではないかと思いますが。

/etc/apt/apt.conf
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でコンテナ側へ持って行ってもいいと思います。

Dockerfile
(略)

# 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を使ってチェックしてあげてくださいね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
76
Help us understand the problem. What are the problem?