跳到正文

Wiki

手動建立Docker映象

約 10 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

Docker 映象是通過 Dockerfile 檔案來構建的。該檔案沒有任何副檔名,檔名固定為 Dockerfile

從本質上來說,Dockerfile 可以看作是一份用於自動化構建映象的指令碼檔案。我們在日常使用 Linux 系統時,在終端中執行的各種安裝、配置命令(例如安裝軟體、修改環境變數等),都可以按照一定的語法規則寫入到 Dockerfile 中。

不過,這些普通的 Shell 命令需要配合 Docker 提供的特定指令(如 RUNCOPYENV 等)一起使用,Docker 才能夠正確解析並執行這些步驟。構建映象的過程,本質上就是按照 Dockerfile 中定義的指令,從上到下一步步執行,最終生成一個可用的映象。

通過這種方式,我們可以將環境配置過程標準化、自動化,從而實現環境的一致性與可復現性。

下面列出了一些常用的 Dockerfile 指令及其作用:

1.DockerFile常用命令

指令 說明 示例
FROM 指定基礎映象,是 Dockerfile 的起點 FROM ubuntu:22.04
LABEL 新增後設資料(如作者、版本等) LABEL maintainer="you@example.com"
ENV 設定環境變數 ENV PORT=8080
ARG 構建引數,只在構建期間可用 ARG VERSION=1.0
RUN 構建映象時執行命令 RUN apt-get update && apt-get install -y curl
COPY 複製檔案到映象中 COPY . /app
ADD 類似 COPY,額外支援解壓 .tar 檔案或遠端 URL(不推薦用於 URL) ADD archive.tar.gz /data/
WORKDIR 設定工作目錄 WORKDIR /opt
CMD 設定容器啟動時預設命令(可被 docker run 覆蓋) CMD ["node", "index.js"]
ENTRYPOINT 設定容器啟動時固定命令(通常用於 CLI 工具等) ENTRYPOINT ["python3"]
EXPOSE 宣告映象內服務監聽的埠(不會自動對映) EXPOSE 80
VOLUME 宣告資料卷掛載點 VOLUME ["/data"]
USER 設定後續命令執行的使用者 USER appuser
ONBUILD 當映象作為其他映象基礎映象時觸發的構建指令 ONBUILD COPY . /src
SHELL 更改預設 shell,比如將 sh -c 改為 bash -c SHELL ["/bin/bash", "-c"]
HEALTHCHECK 定義容器執行時的健康檢查命令 HEALTHCHECK CMD curl --fail http://localhost:8080
STOPSIGNAL 容器停止時傳送的訊號 STOPSIGNAL SIGKILL

2.自己建立容器

2.1.手動建立

首先建立一個資料夾來存放你的Dockerfile 比如我在~/UserFolder/MySource/下建立了一個MyDocker資料夾.

建立好後,在個資料夾下開啟vscode.

cd ~/UserFolder/MySource/MyDocker
code .

在VScode外掛中安裝Dev Containers,Container Tools這倆外掛.

alt text

  1. 外掛1:微軟Docker工具

docker擴充套件外掛已經進化為container tools了,請安裝container tools。

  1. 外掛2:微軟Docker遠端開發工具

下面這是遠端開發的外掛。

接下來建立Dockerfile檔案:

alt text

我們建立一個最簡單的X86架構的映象,這個映象的內容是:

  1. 基於Ubuntu24.04系統的映象
  2. 自帶CUDA和CuDNN
  3. 預設Shell環境為bash
  4. 換源為國內映象源
  5. Shell新增上豐富的顏色
# 基于NVIDIA官方CUDA 12.6和CuDNN基础镜像
FROM nvidia/cuda:12.6.0-cudnn-devel-ubuntu24.04

# 设置环境变量以防止交互安装
ENV DEBIAN_FRONTEND=noninteractive

# 强制使用 Bash 作为默认 Shell
SHELL ["/bin/bash", "-c"]

# 先更新包列表并安装CA证书
RUN apt-get update && apt-get install -y ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 替换为清华大学的DEB822格式镜像源
RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.tuna.tsinghua.edu.cn/ubuntu/|g' /etc/apt/sources.list.d/ubuntu.sources

# 配置终端颜色和提示符
RUN sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/g' /root/.bashrc && \
    # 自定义PS1(带颜色的提示符)
    echo 'export PS1="\[\033[1;36m\]\u@\h\[\033[00m\]:\[\033[1;34m\]\w\[\033[00m\]\$ "' >> /root/.bashrc && \
    # 给ls、grep等命令添加别名
    echo "alias ls='ls --color=auto'" >> /root/.bashrc && \
    echo "alias grep='grep --color=auto'" >> /root/.bashrc && \
    echo "alias ll='ls -alFh --color=auto'" >> /root/.bashrc && \
    # 清理临时文件
    rm -rf /tmp/LS_COLORS

alt text

在x86電腦上編譯x86的映象(一定要有科學的網路環境,不然拉取不了輝達的映象):

命令格式為docker build -t 镜像名称 . 比如:

docker build -t ubuntu24_cuda126_cudnn:latest .

alt text

然後使用docker images命令檢視編譯好的映象.

alt text

2.2.執行此映象

使用run命令的引數非常重要裡的run命令來執行建立好的映象.

應該把--name修改為你要建立的容器的名字,比如ubuntu24cuda126,然後最底下那行應該寫你剛才建立的映象的名字,比如ubuntu24_cuda126_cudnn:latest.

對應本教程的命令應該為:

sudo docker run --name=ubuntu24cuda126 \
--gpus all \
-e NVIDIA_DRIVER_CAPABILITIES=all \
-e DISPLAY=$DISPLAY \
-dit \
--privileged \
--net=host \
--group-add audio \
--group-add video \
--group-add dialout \
-e XAUTHORITY=$HOME/.Xauthority \
-e WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
-e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
-e QT_QPA_PLATFORM=xcb \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
-v /dev/dri:/dev/dri \
-v $HOME/.Xauthority:$HOME/.Xauthority:ro \
-v /run/user/$(id -u)/wayland-0:/run/user/$(id -u)/wayland-0 \
-v /run/user/$(id -u):/run/user/$(id -u) \
-v $HOME:$HOME \
-w $HOME \
ubuntu24_cuda126_cudnn:latest

出現下列這一行,代表成功了.

alt text

可以在VScode的外掛裡看到容器已經成功執行.

alt text

2.3.開啟容器裡的Ubuntu24系統的終端

命令格式為docker exec -it 容器名称 bash 比如:

docker exec -it ubuntu24cuda126 bash

如下圖你已經進入了容器裡的Ubuntu24系統的終端了.

alt text

接下來可以安裝一個neofetch測試一下.

注意,你這裡已經是在root的身份下執行Ubuntu24系統的終端了,所以不需要每條命令前加sudo了,比如sudo apt update可以直接用apt update代替.

apt update
apt install neofetch
neofetch

alt text

然後可以順便測試下輝達驅動和CUDA以及CuDNN的安裝情況:

nvidia-smi
nvcc -V
cat /usr/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

如下圖可知,容器中的Ubuntu24共享了宿主的輝達驅動,版本為595.80. 自帶CUDA12.6與CuDNN9.3.0

alt text

2.4.將映象推送至Docker Hub

將 Docker 映象推送到 Docker Hub 的步驟如下:

  1. 建立 Docker Hub 賬戶

如果你還沒有 Docker Hub 賬戶,請前往 Docker Hub 註冊一個免費賬戶。

  1. 登入 Docker Hub

在終端中使用以下命令登入到你的 Docker Hub 賬戶:

docker login

輸入你的 Docker Hub 使用者名稱和密碼進行驗證。

  1. 為你的映象打標籤

Docker Hub 使用 <用户名>/<镜像名>:<标签> 的格式來標識映象。你需要為你的映象打上標籤,以便能夠推送到 Docker Hub。使用以下命令:

docker tag 镜像名:标签 <你的用户>/新镜像名:标签

例如,如果你的 Docker Hub 使用者名稱是 tungchiahui,你應該執行:

docker tag ubuntu24_cuda126_cudnn:latest tungchiahui/ubuntu24_cuda126_cudnn:latest
  1. 推送映象到 Docker Hub

使用以下命令將映象推送到 Docker Hub:

docker push <你的用户>/镜像名:标签

例如:

docker push tungchiahui/ubuntu24_cuda126_cudnn:latest
  1. 驗證推送成功

你可以通過訪問 Docker Hub 的個人頁面來驗證你的映象是否已成功推送。

注意事項

  • 確保你的映象大小在 Docker Hub 的限制範圍內(一般為 10GB)。

  • 如果你打算將映象公開,可以設定為公共倉庫;如果希望只有你自己可以訪問,可以設定為私有倉庫。

2.5.手動建立(跨平臺多架構構建)(高階的,暫時不用學)

如果您想在 x86/x64 電腦上即為本機x86裝置構建映象,又想為樹莓派、Jetson等ARM64 裝置構建 Docker 映象 ,需要使用 Docker 的跨平臺構建功能 。以下是完整解決方案:


啟用 Docker 跨平臺構建

在 x86 主機上模擬 ARM64 環境需要以下工具:

  1. 啟用 buildx(只需執行一次)
docker buildx create --name multiarch_builder --use

這會建立並啟用一個支援多架構構建的 builder,電腦重啟後也依然存在,所以只用執行一次。

  1. 安裝 QEMU 支援(一般新版 Docker Desktop 已自帶,但是Linux必須要安裝) 如果你用的是伺服器或Linux發行版,確保有 qemu 模擬器:
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

電腦重啟後,就會消失,所以需要你每次電腦重啟後,在buildx命令前,執行一次該命令即可。

  1. 修改dockerfile為多架構版本
# 支持多架构,使用变量指定架构
ARG TARGETARCH

# 基于NVIDIA官方CUDA 12.6和CuDNN基础镜像
FROM --platform=linux/${TARGETARCH} nvidia/cuda:12.6.0-cudnn-devel-ubuntu24.04

# 设置环境变量以防止交互安装
ENV DEBIAN_FRONTEND=noninteractive

# 强制使用 Bash 作为默认 Shell
SHELL ["/bin/bash", "-c"]

# 先更新包列表并安装CA证书
RUN apt-get update && apt-get install -y ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 替换为清华大学的DEB822格式镜像源
RUN if [ "$(dpkg --print-architecture)" = "amd64" ]; then \
        sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.tuna.tsinghua.edu.cn/ubuntu/|g' /etc/apt/sources.list.d/ubuntu.sources; \
    elif [ "$(dpkg --print-architecture)" = "arm64" ]; then \
        sed -i 's|http://ports.ubuntu.com/ubuntu-ports/|https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/|g' /etc/apt/sources.list.d/ubuntu.sources; \
    fi

# 配置终端颜色和提示符
RUN sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/g' /root/.bashrc && \
    # 自定义PS1(带颜色的提示符)
    echo 'export PS1="\[\033[1;36m\]\u@\h\[\033[00m\]:\[\033[1;34m\]\w\[\033[00m\]\$ "' >> /root/.bashrc && \
    # 给ls、grep等命令添加别名
    echo "alias ls='ls --color=auto'" >> /root/.bashrc && \
    echo "alias grep='grep --color=auto'" >> /root/.bashrc && \
    echo "alias ll='ls -alFh --color=auto'" >> /root/.bashrc && \
    # 清理临时文件
    rm -rf /tmp/LS_COLORS
  1. 構建多架構映象 用下面的命令構建 amd64 和 arm64:
docker buildx build --platform linux/amd64,linux/arm64 -t <你的镜像>:<> --push .

例子:

docker buildx build \
--platform linux/amd64,linux/arm64 \
 -t tungchiahui/ubuntu24_cuda126_cudnn:latest \
 --push \
 .

說明: --platform 指定多架構。 --push 是必須的,因為 buildx 的多平臺構建預設是不能本地載入的(除非加 --load,但那隻能支援單一架構)。

2.6.清除構建快取

# 清理BuildKit构建缓存
docker builder prune -f