在X86架构的Windows上构建ARM镜像

前言

Windows上安装Docker参考

https://www.psvmc.cn/article/2021-03-15-docker-windows.html

Docker 镜像是基于基础镜像构建的,基础镜像本身就包含了特定的操作系统和架构信息。

当你在 Dockerfile 中使用 FROM 指令指定基础镜像时,后续在容器内运行的操作都会基于该基础镜像的架构。

注意

在X86上构建ARM镜像会非常慢,我这里测试的镜像时间是构建X86的10倍还多,所以构建的时候要耐心等待。

构建文件

X86

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Pull base image
FROM python:3.9.0

LABEL maintainer="psvmc <psvmc@outlook.com>"

# Set Charset
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Python
RUN mkdir -p /root/.pip
RUN echo "[global]" > /root/.pip/pip.conf && \
echo "index-url = https://mirrors.huaweicloud.com/repository/pypi/simple" >> /root/.pip/pip.conf
RUN pip install pipenv
RUN pip install cmake

# Project
RUN mkdir -p /opt/zapp/
COPY .env /opt/zapp/
COPY main.py /opt/zapp/
COPY Pipfile /opt/zapp/
COPY web /opt/zapp/web
RUN chmod 755 -R /opt/zapp/*
RUN cd /opt/zapp/ && pipenv install --skip-lock

# Expose ports.
EXPOSE 8000

# Define default command.
WORKDIR /opt/zapp/
ENTRYPOINT ["pipenv", "run", "python", "main.py"]

ARM

Dockerfile_ARM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Pull base image
FROM arm64v8/python:3.9.0

LABEL maintainer="psvmc <psvmc@outlook.com>"

# Set Charset
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Python
RUN mkdir -p /root/.pip
RUN echo "[global]" > /root/.pip/pip.conf && \
echo "index-url = https://mirrors.huaweicloud.com/repository/pypi/simple" >> /root/.pip/pip.conf
RUN pip install pipenv
RUN pip install cmake

# Project
RUN mkdir -p /opt/zapp/
COPY .env /opt/zapp/
COPY main.py /opt/zapp/
COPY Pipfile /opt/zapp/
COPY web /opt/zapp/web
RUN chmod 755 -R /opt/zapp/*
RUN cd /opt/zapp/ && pipenv install --skip-lock

# Expose ports.
EXPOSE 8000

# Define default command.
WORKDIR /opt/zapp/
ENTRYPOINT ["pipenv", "run", "python", "main.py"]

构建镜像

构建x86镜像

1
docker build -t psvmc/face_recognition:v0.1 .

运行镜像

1
docker run -p 8000:8000 --name face_recognition psvmc/face_recognition:v0.1

后台运行

1
docker run -d -p 8000:8000 --name face_recognition --restart=always psvmc/face_recognition:v0.1

查看启动日志

1
docker logs face_recognition

删除

1
2
docker stop face_recognition
docker rm face_recognition

构建ARM镜像

QEMU是一个开源的模拟器,它可以在x86架构上模拟ARM架构的环境。

通过执行以下命令来安装QEMU二进制文件:

1
docker run --privileged --rm tonistiigi/binfmt --install all

在包含Dockerfile的目录下,使用以下命令构建ARM镜像:

1
docker buildx build -f Dockerfile_ARM --platform linux/arm64 -t psvmc/face_recognition_arm:v0.1 .

其中

  • --platform linux/arm64 指定了要构建的镜像为ARM 64位架构。

运行ARM镜像

1
docker run --platform linux/arm64 psvmc/face_recognition_arm:v0.1

运行

1
docker run -d -p 8000:8000 --name face_recognition_arm --restart=always psvmc/face_recognition_arm:v0.1

查看启动日志

1
docker logs face_recognition_arm

删除

1
2
docker stop face_recognition_arm
docker rm face_recognition_arm

镜像导出导入

格式

1
2
3
4
# 保存镜像到一个tar包  
docker save image_name -o file_path
# 加载一个tar包格式的镜像
docker load -i file_path

示例

1
2
3
4
# 导出tar包 
docker save psvmc/face_recognition_arm:v0.1 > D:\\face_recognition_arm.tar
# 使用scp将save.tar拷到机器b上,然后:
docker load < /root/face_recognition_arm.tar

查看架构

这里测试一下不通命令构建的架构是不是和基础镜像一致。

aarch64/ARM

Dockerfile_ARCH_ARM

1
2
3
4
5
6
7
8
9
10
11
12
13
# Pull base image
FROM arm64v8/python:3.9.0

# 将当前架构信息写入文件
RUN uname -m > /arch_info.txt

# 定义一个脚本,在容器启动时打印架构信息
RUN echo '#!/bin/sh' > /print_arch.sh && \
echo 'echo "当前架构: $(cat /arch_info.txt)"' >> /print_arch.sh && \
chmod +x /print_arch.sh

# 在容器启动时执行脚本
CMD ["/print_arch.sh"]

构建

1
docker buildx build -f Dockerfile_ARCH_ARM --platform linux/arm64 -t psvmc/arch_arm:v0.1 .

运行

1
docker run --platform linux/arm64 psvmc/arch_arm:v0.1

X86_64/AMD

Dockerfile_ARCH_AMD

1
2
3
4
5
6
7
8
9
10
11
12
13
# Pull base image
FROM python:3.9.0

# 将当前架构信息写入文件
RUN uname -m > /arch_info.txt

# 定义一个脚本,在容器启动时打印架构信息
RUN echo '#!/bin/sh' > /print_arch.sh && \
echo 'echo "当前架构: $(cat /arch_info.txt)"' >> /print_arch.sh && \
chmod +x /print_arch.sh

# 在容器启动时执行脚本
CMD ["/print_arch.sh"]

构建

1
docker buildx build -f Dockerfile_ARCH_AMD -t psvmc/arch_amd:v0.1 .

运行

1
docker run psvmc/arch_amd:v0.1