Docker

Dockerfile

Example

FROM ubuntu

RUN apt-get update
RUN apt-get install -y python-is-python3
RUN apt-get install -y python3-pip
RUN pip3 install flask

WORKDIR /opt/source-code
COPY app.py /opt/source-code
EXPOSE 5000

ENTRYPOINT ["flask","run","--host=0.0.0.0"]

FROM

基礎(きそ) イメージを指定(してい) します。すべてのビルドはここから(はじ) まります。

FROM ubuntu:20.04
FROM golang:1.21-alpine

COPY

ホストからコンテナにファイルを複製(ふくせい) します。

# 単一ファイルを複製
COPY app.go /app/
# ディレクトリ全体を複製
COPY src/ /app/src/

ADD

COPY と() ていますが、追加(ついか) 機能(きのう) があります:ファイルの解凍(かいとう) 、URL からのダウンロード。

# 自動解凍
ADD app.tar.gz /app/
# URL からダウンロード
ADD https://example.com/file.txt /app/

RUN

コマンドを実行(じっこう) し、(あたら) しい Layer を作成(さくせい) します。

# パッケージをインストール
RUN apt-get update && apt-get install -y curl
# 複数行コマンドを実行
RUN set -ex \
    && apt-get update \
    && apt-get install -y \
    python3 \
    python3-pip

CMD

コンテナ起動(きどう) () のデフォルトコマンド。

# 実行形式
CMD ["executable", "param1", "param2"]
# Shell 形式
CMD echo "Hello World"

ENTRYPOINT

コンテナ起動(きどう) () のメインコマンドを設定(せってい) します。上書(うわが) きされにくい。

ENTRYPOINT ["nginx", "-g", "daemon off;"]
# CMD と組み合わせて使用
ENTRYPOINT ["echo"]
# docker run のパラメータで上書き可能
CMD ["Hello World"]

CMD vs ENTRYPOINT

# hard code
FROM ubuntu
CMD ["sleep","5"]

# flex
FROM ubuntu
CMD ["sleep"]

# combined
FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]

LABEL

イメージに metadata を追加(ついか) します。

LABEL version="1.0"
LABEL description="This is my app" \
    maintainer="user@example.com"

EXPOSE

コンテナが使用(しよう) するネットワークポートを宣言(せんげん) します。

EXPOSE 80
EXPOSE 80/tcp
EXPOSE 80/udp

ENV

環境(かんきょう) 変数(へんすう)設定(せってい) します。

ENV APP_HOME /app
ENV VERSION=1.0 DEBUG=true

VOLUME

マウントポイントを作成(さくせい) します。

VOLUME /data
VOLUME ["/data", "/logs"]

USER

コマンドを実行(じっこう) するユーザーを指定(してい) します。

# ユーザー名を使用
USER nginx
# UID を使用
USER 1000

WORKDIR

作業(さぎょう) ディレクトリを設定(せってい) します。

WORKDIR /app
WORKDIR /app/src

ARG

ビルド()変数(へんすう)定義(ていぎ) します。

ARG VERSION=latest
ARG BUILD_DATE
FROM ubuntu:${VERSION}

ONBUILD

() イメージビルド() のトリガー命令(めいれい)定義(ていぎ) します。

ONBUILD COPY . /app/src
ONBUILD RUN /app/src/build.sh

STOPSIGNAL

コンテナを停止(ていし) する(とき)送信(そうしん) するシステムシグナルを設定(せってい) します。

STOPSIGNAL SIGTERM
STOPSIGNAL 9

SHELL

# Windows コンテナ例
SHELL ["powershell", "-Command"]
# Linux コンテナ例
SHELL ["/bin/bash", "-c"]

Multi-Stage Builds

マルチステージビルド(れい)最終(さいしゅう) イメージサイズを削減(さくげん) するために使用(しよう) します。

# ビルドステージ
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

# 最終ステージ
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]

Examples

Go

# ビルドステージ
FROM golang:1.21-alpine AS builder

# ビルドツールをインストール
RUN apk add --no-cache git

# 作業ディレクトリを設定
WORKDIR /app

# go mod ファイルを複製
COPY go.mod go.sum ./

# 依存パッケージをダウンロード
RUN go mod download

# ソースコードを複製
COPY . .

# アプリケーションをビルド
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 最終ステージ
FROM alpine:latest

# 基本ツールをインストール
RUN apk --no-cache add ca-certificates tzdata

# 非 root ユーザーを作成
RUN adduser -D appuser

# 作業ディレクトリを設定
WORKDIR /app

# ビルドステージから実行ファイルを複製
COPY --from=builder /app/main .

# 所有者を変更
RUN chown -R appuser:appuser /app

# 非 root ユーザーに切り替え
USER appuser

# ポートを公開
EXPOSE 8080

# アプリケーションを実行
CMD ["./main"]

Java

# ビルドステージ
FROM maven:3.8.4-openjdk-17 AS builder

# 作業ディレクトリを設定
WORKDIR /app

# pom.xml を複製
COPY pom.xml .

# 依存パッケージをダウンロード(Docker レイヤーキャッシュを活用)
RUN mvn dependency:go-offline

# ソースコードを複製
COPY src ./src

# アプリケーションをビルド
RUN mvn clean package -DskipTests

# 最終ステージ
FROM eclipse-temurin:17-jre-alpine

# 作業ディレクトリを設定
WORKDIR /app

# 非 root ユーザーを作成
RUN addgroup -S spring && adduser -S spring -G spring

# Java オプションを設定
ENV JAVA_OPTS="-Xmx512m -Xms256m"

# タイムゾーンを設定
ENV TZ=Asia/Taipei
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# ビルド成果物(.jar ファイル)を複製
COPY --from=builder /app/target/*.jar app.jar

# 所有者を変更
RUN chown spring:spring /app

# 非 root ユーザーに切り替え
USER spring

# ポートを公開
EXPOSE 8080

# アプリケーションを起動
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Architecture

  flowchart LR
	C((Client))
	Di((Docker image))

	C --->|REST API| Di

Layer Architecture

FROM

RUN

RUN

COPY

ENTRYPOINT

イメージをビルド:

docker build Dockerfile -t lexyu/my-custom-app

コンテナを実行(じっこう) (COPY-ON-WRITE メカニズム):

docker run lexyu/my-custom-app
Docker Layer Architecture

Image

イメージはコンテナの基礎(きそ) として、コンテナの作成(さくせい)実行(じっこう)使用(しよう) されます。軽量(けいりょう)不変(ふへん) のソフトウェアパッケージで、アプリケーション実行(じっこう)必要(ひつよう) なすべてを(ふく) みます:

  • 簡素化(かんそか) された OS(Cut-down OS)
  • 必要(ひつよう)実行(じっこう) 環境(かんきょう)
  • アプリケーションファイル
  • サードパーティライブラリ
  • 環境(かんきょう) 変数(へんすう)

Engine

CLI Call Remote Container API

Containerization

(かく) コンテナ:

  flowchart TD
    Ns((Namespace))
    PID(Process ID)
    UT(Unix Timesharing)
    M(Mount)
    IP(InterProcess)
    Nw(Network)

    Ns <--> PID
    Ns <--> UT
    Ns <--> M
    Ns <--> IP
    Ns <--> Nw

Namespace - PID

Namespace Overview

cgroups

cgroups

Network

Default Networks

Default Networks

User-defined Networks

User-defined Networks

Built-in DNS

Built-in DNS

Multiple Port Mapping

Multiple Port Mapping

Volume

データ共有(きょうゆう)許可(きょか)

  • ホストとコンテナ(かん)
  • コンテナとコンテナ(かん)
Volume
docker run -v /data/mysql:/var/lib/mysql mysql
Docker Volume

--mount-v() わりに使用(しよう)

docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql
Volume Mount

Add Volume into Container From Host

docker run --name website -v ($pwd):/usr/share/nginx/html:ro -d -p 9000:80 nginx
Add Volume into Container From Host

Share Volumes from Specific Container

docker run --name website-copy --volumes-from website -d -p 9001:80 nginx
Share Volume

Docker Registry

すべての Docker イメージの中央(ちゅうおう) リポジトリ:

  • [Registry]/[User/Account]/[Image/Repository]
    • gcr.io/kubernetes-e2e-test-images/dnsutils
    • docker.io/nginx/nginx

Docker Storage

Linux に Docker をインストールした(とき) のファイルシステム:

./var/lib/docker
|_ aufs
|_ containers
|_ image
|_ volumes

Container vs Virtual Machines

Container コンテナ

アプリケーションを実行(じっこう) するための隔離(かくり) された環境(かんきょう)複数(ふくすう) のアプリケーションを隔離(かくり) された環境(かんきょう)実行(じっこう) できます:

  • 軽量(けいりょう)
  • ホストの OS を使用(しよう)
  • 起動(きどう)(はや)
  • ハードウェアリソースが(すく) なくて()
Containers

Virtual Machines 仮想マシン

マシン(物理(ぶつり) ハードウェア)の抽象化(ちゅうしょうか)問題点(もんだいてん)

  • (かく) 仮想(かそう) マシンに完全(かんぜん) な OS が必要(ひつよう)
  • 起動(きどう)(おそ)
  • リソースを(おお)消費(しょうひ)
Virtual Machines

ハイパーバイザー(Hypervisor):仮想(かそう) マシンを管理(かんり) するプログラム。

Docker on Windows

Windows Container Types