Dockerfileの環境変数・プロキシ・タイムゾーン設定まとめ

Dockerコンテナを開発環境や本番環境で運用する際、多くのエンジニアが直面するのが「環境変数が反映されない」「社内プロキシ環境下でビルドがタイムアウトする」「コンテナ内のログがUTC(世界協定時)になって時刻が9時間ズレる」というトラブルです。

特に ARG と ENV のスコープの違いや、マルチステージビルドにおける変数の消失、社内プロキシ(HTTP_PROXY)の引き回し、そして機密情報(APIキーやトークン)の安全な注入方法は、Docker初学者から実務エンジニアまで頻出のつまずきポイントとなっています。

この記事では、Dockerfileにおける環境変数の設定ルール(ARG と ENV の使い分け)、企業ネットワークでのプロキシ透過設定、OS別のタイムゾーン(JST: Asia/Tokyo)設定、そしてBuildKitを活用したシークレット管理までをコード例付きで体系的にまとめました。

この記事で行うこと

  • ビルド時限定の ARG とコンテナ実行時も永続化する ENV の違いと使い分けを理解します
  • マルチステージビルドで FROM ごとに ARG のスコープがリセットされる罠と回避策を学びます
  • 社内プロキシをDockerfileに直書きせず、--build-arg で安全に注入する手順を整理します
  • Ubuntu/Debian系およびAlpine Linuxでタイムゾーンを日本時間(Asia/Tokyo)に設定します
  • BuildKitの --mount=type=secret を使い、イメージ履歴に機密情報を残さないビルド手法を把握します

前提条件・対象読者

  • 対象環境:Docker Engine / Docker Desktop / WSL2コンテナ環境(BuildKit有効環境)
  • 対応バージョン:Docker 20.10以降(BuildKit標準搭載バージョン、最終確認:2026年11月)
  • バージョン確認コマンド:docker --version および docker buildx version

1. Dockerfile環境変数・プロキシ・タイムゾーン早見表

まずは、現場ですぐにコピペして使える各種設定のベストプラクティス早見表です。

設定項目推奨される記述方法備考・適用スコープ
ビルド時の一時変数(ARG)ARG NODE_VERSION=20.xビルド時のみ有効。コンテナ実行時には残らない
コンテナ永続環境変数(ENV)ENV NODE_ENV=productionビルド時および実行時(ランタイム)の両方で有効
タイムゾーン設定(Ubuntu/Debian)ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
tzdata パッケージを導入してシンボリックリンク作成
タイムゾーン設定(Alpine Linux)RUN apk add --no-cache tzdata && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtimeAlpine用の軽量なJST設定手順
ビルド時プロキシ引数渡しdocker build --build-arg HTTP_PROXY=$HTTP_PROXY .Dockerfile内へのハードコードを避けポータビリティを維持
機密情報の安全なマウントRUN --mount=type=secret,id=token cat /run/secrets/tokenイメージレイヤーに秘密情報を残さないBuildKit機能

2. ARGとENVの決定的な違いと使い分け

Dockerfileで変数を定義する際、最も混同しやすいのが ARG と ENV です。

ARG:ビルド時のみ有効な引数

ARG で宣言した変数は、docker build コマンド実行中にのみ参照できます。コンテナが起動した後のランタイム環境には引き継がれません。

# 基本的なARGの宣言とデフォルト値
ARG APP_VERSION=1.0.0

# ビルド時に外部から上書き可能
# docker build --build-arg APP_VERSION=2.0.0 .

注意点として、ARG の値はコンテナ起動後の環境変数には残りませんが、docker history コマンドを実行するとイメージレイヤーのビルド履歴として平文で閲覧可能です。そのため、パスワードや秘密鍵を ARG で渡すのはセキュリティ上避ける必要があります。

ENV:コンテナ実行時にも残る永続環境変数

ENV で設定した変数は、ビルド中だけでなく、コンテナが起動してアプリケーションが動作している間もOSの環境変数として永続化されます。

ENV PORT=8080
ENV NODE_ENV=production

# 実行時コマンドで参照可能
EXPOSE $PORT
CMD ["node", "server.js"]

マルチステージビルドでの落とし穴:FROMごとのスコープリセット

マルチステージビルドを使用する場合、ARG の有効範囲(スコープ)は各 FROM 命令の直下でリセットされます。

# グローバルスコープのARG(FROM行でのみ使用可能)
ARG BASE_TAG=20-slim

FROM node:${BASE_TAG} AS builder
# ここで再度ARGを宣言しないとBUILD_TARGETは空になる
ARG BUILD_TARGET=production
RUN echo "Building for: ${BUILD_TARGET}"

FROM node:${BASE_TAG} AS runner
# runnerステージでも再度宣言が必要
ARG BUILD_TARGET=production
ENV TARGET=${BUILD_TARGET}

「1行目で ARG を書いたのに後続ステージで参照できない」という場合は、該当ステージの FROM 直下で再宣言されているか確認してください。

3. 社内プロキシ環境下でのDockerfileビルド設定

企業の社内ネットワークやVPN環境では、外部インターネットへのアクセスにプロキシサーバーの経由が必須となるケースがあります。

DockerfileにプロキシURLをハードコードしない

初心者がやりがちなアンチパターンが、Dockerfile内に直接プロキシURLを書き込んでしまうことです。

# ❌ 間違い例(社内環境専用のURLが固定化され、社外やCI/CDでビルドできなくなる)
ENV http_proxy=http://proxy.company.local:8080

これを行うと、リポジトリをクラウドCI/CD(GitHub Actions等)や自宅環境でビルドした際にプロキシ接続エラーで失敗します。

⭕ 正しい手順:ビルド引数(–build-arg)で外部から注入する

プロキシ情報はDockerfile内には記述せず、ビルドコマンドの引数として渡します。Dockerは標準定義されたプロキシ用Build-time変数(HTTP_PROXY, HTTPS_PROXY, NO_PROXY および小文字版)を自動認識します。

# プロキシ環境変数を渡してビルド(イメージ履歴にも残らない標準予約変数)
docker build \
  --build-arg HTTP_PROXY="http://proxy.example.com:8080" \
  --build-arg HTTPS_PROXY="http://proxy.example.com:8080" \
  --build-arg NO_PROXY="localhost,127.0.0.1,.example.com" \
  -t my-app .

パッケージマネージャーごとの追加設定

OSの基本パッケージ(apt 等)をインストールする際、環境によっては明示的なプロキシ設定が必要になる場合があります。

Debian / Ubuntu系でビルド時のみプロキシを適用し、設定痕跡を残さない書き方:

ARG HTTP_PROXY
ARG HTTPS_PROXY

RUN if [ -n "$HTTP_PROXY" ]; then \
      echo "Acquire::http::Proxy \"$HTTP_PROXY\";" > /etc/apt/apt.conf.d/01proxy; \
      echo "Acquire::https::Proxy \"$HTTPS_PROXY\";" >> /etc/apt/apt.conf.d/01proxy; \
    fi && \
    apt-get update && apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/* && \
    rm -f /etc/apt/apt.conf.d/01proxy

ビルド終了時に /etc/apt/apt.conf.d/01proxy を削除しておくことで、完成したイメージに社内プロキシ情報を残さないクリーンな設計が実現できます。

4. タイムゾーン(JST: Asia/Tokyo)の正しい設定方法

Docker公式のベースイメージの多くは、タイムゾーンがデフォルトでUTC(世界協定時)に設定されています。

コンテナ内のログ記録、日次バッチ処理、データベースのタイムスタンプを日本時間(JST = UTC+9)に合わせるには、OSに応じたタイムゾーン設定を適用します。

Debian / Ubuntu系ベースイメージでの設定

FROM ubuntu:24.04

# 対話型プロンプトの抑止とタイムゾーン環境変数の指定
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Tokyo

RUN apt-get update && apt-get install -y --no-install-recommends \
    tzdata && \
    ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

ポイントは DEBIAN_FRONTEND=noninteractive を指定することです。これを忘れると、tzdata のインストール中に地域選択の対話プロンプトが表示され、ビルドが途中で停止してしまいます。

Alpine Linuxベースイメージでの設定

軽量なAlpineイメージでは、パッケージマネージャーが apk となり、以下の手順で設定します。

FROM alpine:3.20

ENV TZ=Asia/Tokyo

RUN apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone && \
    apk del tzdata

Alpineでは /usr/share/zoneinfo/Asia/Tokyo を /etc/localtime にコピーした後、不要になった tzdata パッケージを削除(apk del tzdata)することで、イメージサイズを小さく保てます。

5. 機密情報を安全に渡すBuildKit Secretsの活用

GitHubのプライベートリポジトリから依存パッケージを取得する際や、社内パッケージレジストリ(npm, pip)へアクセスする際、認証トークンが必要になります。

❌ やってはいけない例:ARGによるトークン渡し

# ❌ 危険:イメージのレイヤー履歴(docker history)にトークンが残る
ARG GITHUB_TOKEN
RUN git clone https://${GITHUB_TOKEN}@github.com/myorg/private-repo.git

この方法で作成されたイメージは、docker history --no-trunc を実行するだけでトークン文字列が平文で見えてしまいます。

⭕ 推奨される方法:BuildKitのシークレットマウント

Docker BuildKitの RUN --mount=type=secret を使用すると、該当の RUN ステップ実行中のみ一時ファイル(デフォルトは /run/secrets/<id>)としてメモリ上にマウントされ、完成したイメージレイヤーには一切データや履歴が残りません。

Dockerfile側の記述:

# syntax=docker/dockerfile:1
FROM python:3.12-slim

# シークレットを一時ファイルとしてマウントしてpip認証に利用
RUN --mount=type=secret,id=pip_conf \
    PIP_CONFIG_FILE=/run/secrets/pip_conf pip install --no-cache-dir my-private-package

ビルドコマンド実行時の記述:

# ローカルの秘密設定ファイルをシークレットとして渡す
docker build --secret id=pip_conf,src=$HOME/.pip/pip.conf -t my-app .

6. よくある質問(FAQ)

Q1. ARGやENVで設定した値がCMDやENTRYPOINTで展開されません。

CMD や ENTRYPOINT をJSON配列形式(exec形式: ["node", "$START_FILE"])で記述した場合、シェルを介さずに直接プロセスが起動されるため、環境変数($START_FILE)が展開されません。変数を展開したい場合は、明示的にシェル(sh -c)を呼び出す形式で記述します。

# ❌ exec形式そのままでは変数が展開されない
CMD ["node", "$START_FILE"]

# ⭕ sh -c を経由させることで変数が展開され、シグナルもexecで引き継げる
CMD ["sh", "-c", "exec node $START_FILE"]

Q2. /etc/localtime を変更したのにアプリ側の時刻がUTCのままです。

JavaやNode.js、Pythonなどのランタイムによっては、環境変数 TZ が明示されていないとUTCへフォールバックする場合があります。Dockerfile内に必ず ENV TZ=Asia/Tokyo を記述しておいてください。

まとめ

Dockerfileにおける環境変数・プロキシ・タイムゾーン設定の要点は以下の4つです。

  1. ビルド時限定の値は ARG、コンテナ実行時も必要な値は ENV を使い分ける
  2. 社内プロキシはDockerfileに直書きせず、--build-arg HTTP_PROXY=... で外部から渡す
  3. タイムゾーンは ENV TZ=Asia/Tokyo と /etc/localtime の設定をセットで行う
  4. 認証トークン等の機密情報は ARG ではなく RUN --mount=type=secret で安全にマウントする

次に読むおすすめ記事

WSL2とDockerを組み合わせたWindows開発環境の構築手順や頻出トラブルの解決策を体系的に学びたい方は、以下のまとめ記事もあわせて参考にしてください。

WSL2+Dockerで作るWindows開発環境構築まとめ
WindowsマシンでWeb開発やバックエンド開発、AIアプリ開発を行う際、いまや欠かせない標準構成となったのが「Windows + WSL2 + Docker + VS Code」の組み合わせです。かつては「Web開発といえばMac一択」…

Dockerfileのビルドエラー対策やマルチステージビルドのキャッシュ最適化については、以下の個別記事で詳しく解説しています。

参考情報