Skip to content

03.Docker 镜像

Dockefile

Dockerfile 是 docker 可以识别的文件,其制定了 docker 构建镜像的规则。

Dockerfile 的规则为 INSTRUCTION ARGUMENT

Dockerfile 以 FROM 指令开始,表示基于某操作系统或之前创建的操作系统。

Docker 层

在根据 Dockerfile 构建镜像时,每一句指令都会基于上一层创建一个新层,且创建的层只包含相对于上一层的修改,这点将反映在最终构建的镜像的大小上。

案例:创建一个 Docker 镜像

TIP

本案例将创建一个简单的 flask 程序 docker 镜像,用以展示 docker 镜像的创建过程。

通过此案例,你将可以学到:

指令执行过程中,如果需要切换镜像源,请进行一下操作:

  1. 首先查看当前的 Ubuntu 版本

    bash
    cat /etc/os-release
  2. 根据 Ubuntu 版本代号,手动替换镜像源为阿里云

    bash
    cat > /etc/apt/sources.list <<EOF
    deb http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse
    
    deb-src http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
    deb-src http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
    deb-src http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
    deb-src http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse
    EOF

    根据实际版本替换 noble 为正确的版本代号:

    • Ubuntu 24.04: noble
    • Ubuntu 20.04: focal
    • Ubuntu 18.04: bionic
  3. 如果是 Debian 12 (Bookworm) 版本,执行:

    bash
    cat > /etc/apt/sources.list <<EOF
    deb http://mirrors.aliyun.com/debian/ bookworm main contrib non-free non-free-firmware
    deb http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free non-free-firmware
    deb http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free non-free-firmware
    EOF

以下指南说明了一步一步在 cmd 中创建镜像的执行过程,该过程不需要一步步执行,只需阅读,后文将给出标准的执行过程:

执行 docker run -it ubuntu bash

cmd
C:\>docker run -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
de44b265507a: Pull complete
Digest: sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab
Status: Downloaded newer image for ubuntu:latest

其中, -it 参数?

由于原本机器上并没有 ubuntu 的镜像,因此将从官方 hub 下载该镜像并运行。

尝试安装 python,执行指令 apt install -y python3

cmd
root@a2308dc17faf:/# apt install -y python3
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package python3

由于没有更新软件包,因此无法找到 python,因此,首先更新软件包,执行 apt update

cmd
root@a2308dc17faf:/# apt update
Get:1 http://mirrors.aliyun.com/ubuntu noble InRelease [256 kB]
Get:2 http://mirrors.aliyun.com/ubuntu noble-updates InRelease [126 kB]
Get:3 http://mirrors.aliyun.com/ubuntu noble-backports InRelease [126 kB]
Get:4 http://mirrors.aliyun.com/ubuntu noble-security InRelease [126 kB]
Get:5 http://mirrors.aliyun.com/ubuntu noble/restricted Sources [21.8 kB]
Get:6 http://mirrors.aliyun.com/ubuntu noble/universe Sources [24.3 MB]
Get:7 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Get:8 http://mirrors.aliyun.com/ubuntu noble/main Sources [1713 kB]
Get:9 http://mirrors.aliyun.com/ubuntu noble/multiverse Sources [355 kB]
Get:10 http://archive.ubuntu.com/ubuntu noble-backports InRelease [126 kB]
Get:11 http://mirrors.aliyun.com/ubuntu noble/multiverse amd64 Packages [331 kB]
Get:12 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages [737 kB]
Get:13 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages [1035 kB]
Get:14 http://mirrors.aliyun.com/ubuntu noble/universe amd64 Packages [19.3 MB]
Get:15 http://mirrors.aliyun.com/ubuntu noble/main amd64 Packages [1808 kB]
Get:16 http://mirrors.aliyun.com/ubuntu noble/restricted amd64 Packages [117 kB]
Get:17 http://mirrors.aliyun.com/ubuntu noble-updates/universe Sources [485 kB]
Get:18 http://archive.ubuntu.com/ubuntu noble InRelease [256 kB]
Get:19 http://mirrors.aliyun.com/ubuntu noble-updates/main Sources [409 kB]
Get:20 http://mirrors.aliyun.com/ubuntu noble-updates/restricted Sources [27.6 kB]
Get:21 http://mirrors.aliyun.com/ubuntu noble-updates/multiverse Sources [13.1 kB]
Get:22 http://mirrors.aliyun.com/ubuntu noble-updates/multiverse amd64 Packages [19.7 kB]
Get:23 http://mirrors.aliyun.com/ubuntu noble-updates/restricted amd64 Packages [737 kB]
Get:24 http://mirrors.aliyun.com/ubuntu noble-updates/universe amd64 Packages [1263 kB]
Get:25 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 Packages [978 kB]
Get:26 http://mirrors.aliyun.com/ubuntu noble-backports/universe Sources [8260 B]
Get:27 http://mirrors.aliyun.com/ubuntu noble-backports/universe amd64 Packages [11.9 kB]
Get:28 http://mirrors.aliyun.com/ubuntu noble-security/multiverse Sources [7774 B]
Get:29 http://archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB]
Get:30 http://mirrors.aliyun.com/ubuntu noble-security/main Sources [176 kB]
Get:31 http://mirrors.aliyun.com/ubuntu noble-security/restricted Sources [25.6 kB]
Get:32 http://mirrors.aliyun.com/ubuntu noble-security/universe Sources [373 kB]
Get:33 http://mirrors.aliyun.com/ubuntu noble-security/restricted amd64 Packages [722 kB]
Get:34 http://security.ubuntu.com/ubuntu noble-security/restricted amd64 Packages [722 kB]
Get:35 http://mirrors.aliyun.com/ubuntu noble-security/main amd64 Packages [737 kB]
Get:36 http://mirrors.aliyun.com/ubuntu noble-security/universe amd64 Packages [1035 kB]
Get:37 http://archive.ubuntu.com/ubuntu noble-backports/universe amd64 Packages [11.9 kB]
Get:38 http://mirrors.aliyun.com/ubuntu noble-security/multiverse amd64 Packages [15.5 kB]
Get:39 http://security.ubuntu.com/ubuntu noble-security/multiverse amd64 Packages [15.5 kB]
Get:40 http://archive.ubuntu.com/ubuntu noble/restricted amd64 Packages [117 kB]
Get:41 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages [19.3 MB]
Get:42 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages [1808 kB]
Get:43 http://archive.ubuntu.com/ubuntu noble/multiverse amd64 Packages [331 kB]
Get:44 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages [978 kB]
Get:45 http://archive.ubuntu.com/ubuntu noble-updates/multiverse amd64 Packages [19.7 kB]
Get:46 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages [1263 kB]
Get:47 http://archive.ubuntu.com/ubuntu noble-updates/restricted amd64 Packages [737 kB]
Fetched 82.3 MB in 55s (1506 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.

再次安装 python :

cmd
root@a2308dc17faf:/# apt install -y python3
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  ca-certificates libexpat1 libpython3-stdlib libpython3.12-minimal libpython3.12-stdlib libreadline8t64 libsqlite3-0
  media-types netbase openssl python3-minimal python3.12 python3.12-minimal readline-common tzdata
Suggested packages:
  python3-doc python3-tk python3-venv python3.12-venv python3.12-doc binutils binfmt-support readline-doc
The following NEW packages will be installed:
  ca-certificates libexpat1 libpython3-stdlib libpython3.12-minimal libpython3.12-stdlib libreadline8t64 libsqlite3-0
  media-types netbase openssl python3 python3-minimal python3.12 python3.12-minimal readline-common tzdata
0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.
Need to get 8421 kB of archives.
After this operation, 30.2 MB of additional disk space will be used.
Get:1 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 libpython3.12-minimal amd64 3.12.3-1ubuntu0.3 [834 kB]
Get:2 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 libexpat1 amd64 2.6.1-2ubuntu0.2 [87.4 kB]
Get:3 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 python3.12-minimal amd64 3.12.3-1ubuntu0.3 [2333 kB]
Get:4 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 python3-minimal amd64 3.12.3-0ubuntu2 [27.4 kB]
Get:5 http://mirrors.aliyun.com/ubuntu noble/main amd64 media-types all 10.1.0 [27.5 kB]
Get:6 http://mirrors.aliyun.com/ubuntu noble/main amd64 netbase all 6.4 [13.1 kB]
Get:7 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 tzdata all 2024a-3ubuntu1.1 [273 kB]
Get:8 http://mirrors.aliyun.com/ubuntu noble/main amd64 readline-common all 8.2-4build1 [56.5 kB]
Get:9 http://mirrors.aliyun.com/ubuntu noble/main amd64 libreadline8t64 amd64 8.2-4build1 [153 kB]
Get:10 http://mirrors.aliyun.com/ubuntu noble/main amd64 libsqlite3-0 amd64 3.45.1-1ubuntu2 [701 kB]
Get:11 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 libpython3.12-stdlib amd64 3.12.3-1ubuntu0.3 [2068 kB]
Get:12 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 python3.12 amd64 3.12.3-1ubuntu0.3 [651 kB]
Get:13 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 libpython3-stdlib amd64 3.12.3-0ubuntu2 [10.0 kB]
Get:14 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 python3 amd64 3.12.3-0ubuntu2 [23.0 kB]
Get:15 http://mirrors.aliyun.com/ubuntu noble-updates/main amd64 openssl amd64 3.0.13-0ubuntu3.4 [1003 kB]
Get:16 http://mirrors.aliyun.com/ubuntu noble/main amd64 ca-certificates all 20240203 [159 kB]
Fetched 8421 kB in 5s (1748 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libpython3.12-minimal:amd64.
(Reading database ... 4379 files and directories currently installed.)
Preparing to unpack .../libpython3.12-minimal_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking libpython3.12-minimal:amd64 (3.12.3-1ubuntu0.3) ...
Selecting previously unselected package libexpat1:amd64.
Preparing to unpack .../libexpat1_2.6.1-2ubuntu0.2_amd64.deb ...
Unpacking libexpat1:amd64 (2.6.1-2ubuntu0.2) ...
Selecting previously unselected package python3.12-minimal.
Preparing to unpack .../python3.12-minimal_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking python3.12-minimal (3.12.3-1ubuntu0.3) ...
Setting up libpython3.12-minimal:amd64 (3.12.3-1ubuntu0.3) ...
Setting up libexpat1:amd64 (2.6.1-2ubuntu0.2) ...
Setting up python3.12-minimal (3.12.3-1ubuntu0.3) ...
Selecting previously unselected package python3-minimal.
(Reading database ... 4698 files and directories currently installed.)
Preparing to unpack .../0-python3-minimal_3.12.3-0ubuntu2_amd64.deb ...
Unpacking python3-minimal (3.12.3-0ubuntu2) ...
Selecting previously unselected package media-types.
Preparing to unpack .../1-media-types_10.1.0_all.deb ...
Unpacking media-types (10.1.0) ...
Selecting previously unselected package netbase.
Preparing to unpack .../2-netbase_6.4_all.deb ...
Unpacking netbase (6.4) ...
Selecting previously unselected package tzdata.
Preparing to unpack .../3-tzdata_2024a-3ubuntu1.1_all.deb ...
Unpacking tzdata (2024a-3ubuntu1.1) ...
Selecting previously unselected package readline-common.
Preparing to unpack .../4-readline-common_8.2-4build1_all.deb ...
Unpacking readline-common (8.2-4build1) ...
Selecting previously unselected package libreadline8t64:amd64.
Preparing to unpack .../5-libreadline8t64_8.2-4build1_amd64.deb ...
Adding 'diversion of /lib/x86_64-linux-gnu/libhistory.so.8 to /lib/x86_64-linux-gnu/libhistory.so.8.usr-is-merged by libreadline8t64'
Adding 'diversion of /lib/x86_64-linux-gnu/libhistory.so.8.2 to /lib/x86_64-linux-gnu/libhistory.so.8.2.usr-is-merged by libreadline8t64'
Adding 'diversion of /lib/x86_64-linux-gnu/libreadline.so.8 to /lib/x86_64-linux-gnu/libreadline.so.8.usr-is-merged by libreadline8t64'
Adding 'diversion of /lib/x86_64-linux-gnu/libreadline.so.8.2 to /lib/x86_64-linux-gnu/libreadline.so.8.2.usr-is-merged by libreadline8t64'
Unpacking libreadline8t64:amd64 (8.2-4build1) ...
Selecting previously unselected package libsqlite3-0:amd64.
Preparing to unpack .../6-libsqlite3-0_3.45.1-1ubuntu2_amd64.deb ...
Unpacking libsqlite3-0:amd64 (3.45.1-1ubuntu2) ...
Selecting previously unselected package libpython3.12-stdlib:amd64.
Preparing to unpack .../7-libpython3.12-stdlib_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking libpython3.12-stdlib:amd64 (3.12.3-1ubuntu0.3) ...
Selecting previously unselected package python3.12.
Preparing to unpack .../8-python3.12_3.12.3-1ubuntu0.3_amd64.deb ...
Unpacking python3.12 (3.12.3-1ubuntu0.3) ...
Selecting previously unselected package libpython3-stdlib:amd64.
Preparing to unpack .../9-libpython3-stdlib_3.12.3-0ubuntu2_amd64.deb ...
Unpacking libpython3-stdlib:amd64 (3.12.3-0ubuntu2) ...
Setting up python3-minimal (3.12.3-0ubuntu2) ...
Selecting previously unselected package python3.
(Reading database ... 5703 files and directories currently installed.)
Preparing to unpack .../python3_3.12.3-0ubuntu2_amd64.deb ...
Unpacking python3 (3.12.3-0ubuntu2) ...
Selecting previously unselected package openssl.
Preparing to unpack .../openssl_3.0.13-0ubuntu3.4_amd64.deb ...
Unpacking openssl (3.0.13-0ubuntu3.4) ...
Selecting previously unselected package ca-certificates.
Preparing to unpack .../ca-certificates_20240203_all.deb ...
Unpacking ca-certificates (20240203) ...
Setting up media-types (10.1.0) ...
Setting up libsqlite3-0:amd64 (3.45.1-1ubuntu2) ...
Setting up tzdata (2024a-3ubuntu1.1) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 79.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC entries checked: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.38.2 /usr/local/share/perl/5.38.2 /usr/lib/x86_64-linux-gnu/perl5/5.38 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl-base /usr/lib/x86_64-linux-gnu/perl/5.38 /usr/share/perl/5.38 /usr/local/lib/site_perl) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 8.)
debconf: falling back to frontend: Teletype
Configuring tzdata
------------------

Please select the geographic area in which you live. Subsequent configuration questions will narrow this down by
presenting a list of cities, representing the time zones in which they are located.

  1. Africa   3. Antarctica  5. Asia      7. Australia  9. Indian    11. Etc
  2. America  4. Arctic      6. Atlantic  8. Europe     10. Pacific

Geographic area: 1

Please select the city or region corresponding to your time zone.

  1. Abidjan      9. Bissau        17. Dakar          25. Johannesburg  33. Lome        41. Mogadishu    49. Sao_Tome
  2. Accra        10. Blantyre     18. Dar_es_Salaam  26. Juba          34. Luanda      42. Monrovia     50. Timbuktu
  3. Addis_Ababa  11. Brazzaville  19. Djibouti       27. Kampala       35. Lubumbashi  43. Nairobi      51. Tripoli
  4. Algiers      12. Bujumbura    20. Douala         28. Khartoum      36. Lusaka      44. Ndjamena     52. Tunis
  5. Asmara       13. Cairo        21. El_Aaiun       29. Kigali        37. Malabo      45. Niamey       53. Windhoek
  6. Bamako       14. Casablanca   22. Freetown       30. Kinshasa      38. Maputo      46. Nouakchott
  7. Bangui       15. Ceuta        23. Gaborone       31. Lagos         39. Maseru      47. Ouagadougou
  8. Banjul       16. Conakry      24. Harare         32. Libreville    40. Mbabane     48. Porto-Novo
Time zone: 1


Current default time zone: 'Africa/Abidjan'
Local time is now:      Sat Jan 11 13:53:39 GMT 2025.
Universal Time is now:  Sat Jan 11 13:53:39 UTC 2025.
Run 'dpkg-reconfigure tzdata' if you wish to change it.

Setting up netbase (6.4) ...
Setting up openssl (3.0.13-0ubuntu3.4) ...
Setting up readline-common (8.2-4build1) ...
Setting up ca-certificates (20240203) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 79.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC entries checked: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.38.2 /usr/local/share/perl/5.38.2 /usr/lib/x86_64-linux-gnu/perl5/5.38 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl-base /usr/lib/x86_64-linux-gnu/perl/5.38 /usr/share/perl/5.38 /usr/local/lib/site_perl) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 8.)
debconf: falling back to frontend: Teletype
Updating certificates in /etc/ssl/certs...
146 added, 0 removed; done.
Setting up libreadline8t64:amd64 (8.2-4build1) ...
Setting up libpython3.12-stdlib:amd64 (3.12.3-1ubuntu0.3) ...
Setting up python3.12 (3.12.3-1ubuntu0.3) ...
Setting up libpython3-stdlib:amd64 (3.12.3-0ubuntu2) ...
Setting up python3 (3.12.3-0ubuntu2) ...
running python rtupdate hooks for python3.12...
running python post-rtupdate hooks for python3.12...
Processing triggers for libc-bin (2.39-0ubuntu8.3) ...
Processing triggers for ca-certificates (20240203) ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
W: Operation was interrupted before it could finish

由于是最精简的 ubuntu 镜像,因此一些依赖等可能没有安装,在安装 python 时,某些步骤中需要手动交互。

如果不需要手动交互,请执行 DEBIAN_FRONTEND=noninteractive apt install -y python3 ,设置 debconf 使用非交互模式,跳过手动输入。

安装 pipapt install python3-pip ,检查 pip 是否安装成功:

cmd
root@4e59a13d30cd:/# pip list
Package    Version
---------- -------
pip        24.0
setuptools 68.1.2
wheel      0.42.0

切换全局 pip 镜像源为阿里云:

cmd
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

安装 flask 包, pip install flask --break-system-packages

默认配置下的 pip 环境中,由于 PEP 668 的限制,无法直接在系统环境中安装第三方库,可以使用 --break-system-packages 强制安装。

cmd
root@a2308dc17faf:/# pip install flask --break-system-packages
Looking in indexes: https://mirrors.aliyun.com/pypi/simple/
Collecting flask
  Downloading https://mirrors.aliyun.com/pypi/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl (102 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 103.0/103.0 kB 4.8 MB/s eta 0:00:00
Collecting Werkzeug>=3.1 (from flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl (224 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 224.5/224.5 kB 4.5 MB/s eta 0:00:00
Collecting Jinja2>=3.1.2 (from flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl (134 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 134.6/134.6 kB 4.3 MB/s eta 0:00:00
Collecting itsdangerous>=2.2 (from flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Collecting click>=8.1.3 (from flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl (98 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.2/98.2 kB 8.3 MB/s eta 0:00:00
Collecting blinker>=1.9 (from flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl (8.5 kB)
Collecting MarkupSafe>=2.0 (from Jinja2>=3.1.2->flask)
  Downloading https://mirrors.aliyun.com/pypi/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (23 kB)
Installing collected packages: MarkupSafe, itsdangerous, click, blinker, Werkzeug, Jinja2, flask
Successfully installed Jinja2-3.1.5 MarkupSafe-3.0.2 Werkzeug-3.1.3 blinker-1.9.0 click-8.1.8 flask-3.1.0 itsdangerous-2.2.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

写入 flask 代码:

cmd
root@a2308dc17faf:/# cat > /opt/app.py
import os
from flask import Flask

app = Flask(__name__)


@app.route("/")
def main():
        return "Welcome!"


@app.route("/how are you")
def hello():
        return "I am good, how about you?"


if __name__ == "__main__":
        app.run()

^C
root@a2308dc17faf:/#

进入目录执行该 py 文件:

cmd
root@a2308dc17faf:/# cd opt/
root@a2308dc17faf:/opt# FLASK_APP=app.py flask run --host=0.0.0.0
 * Serving Flask app 'app.py'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.17.0.2:5000
Press CTRL+C to quit

现在,执行 history 指令可以看到历史执行过的所有指令,将其中在创建全新镜像时需要执行的指令保存:

cmd
root@a2308dc17faf:/opt# history
    1  python
    2  python3
    3  apt install -y python3
    4  apt update
    5  cat > /etc/apt/sources.list <<EOF
deb http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse
EOF

    6  apt update
    7  apt install -y python3
    8  apt install -y python
    9  pip install
   10  apt install -y python3 python3-pip
   11  pip install flask
   12  pip install flask --break-system-packages
   13  pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
   14  pip install flask --break-system-packages
   15  cat > /opt/app.py
   16  FLASK_APP=app.py flask run --host=0.0.0.0
   17  FLASK_APP=app flask run --host=0.0.0.0
   18  flask run --host=0.0.0.0
   19  cd opt/
   20  flask run --host=0.0.0.0
   21  FLASK_APP=app flask run --host=0.0.0.0
   22  FLASK_APP=app.py flask run --host=0.0.0.0
   23  history

这里保存为一份草稿,记录了需要执行的指令,其中,将需要交互式安装 python 的指令替换为了非交互式安装:

cat > /etc/apt/sources.list <<EOF
deb http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse

deb-src http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse
EOF

apt update

DEBIAN_FRONTEND=noninteractive apt install -y python3

apt install -y python3-pip

pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

pip install flask --break-system-packages

复制app.py代码

cd opt/

FLASK_APP=app.py flask run --host=0.0.0.0

推出容器,并检查当前该容器没有再运行中:

cmd
root@a2308dc17faf:/opt# exit
exit

C:\>docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

构建 Dockerfile

将需要执行的指令规整为 Dockerfile ,其中,将更换 ubuntu 镜像源的部分使用 echo 代替,因为默认 dockerfile 中不支持指令换行执行:

dockerfile
FROM ubuntu

# 替换镜像源
RUN echo "deb http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse" > /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://mirrors.aliyun.com/ubuntu noble-updates main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://mirrors.aliyun.com/ubuntu noble-backports main restricted universe multiverse" >> /etc/apt/sources.list && \
    echo "deb-src http://mirrors.aliyun.com/ubuntu noble-security main restricted universe multiverse" >> /etc/apt/sources.list

RUN apt update

RUN DEBIAN_FRONTEND=noninteractive apt install -y python3

RUN apt install -y python3-pip

RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/

RUN pip install flask --break-system-packages

COPY app.py opt/app.py

# 启动 Flask 应用
ENTRYPOINT FLASK_APP=opt/app.py flask run --host=0.0.0.0

构建镜像:

cmd
X:\docker-flask>docker build . -t docker-flask-simple
[+] Building 69.3s (13/13) FINISHED                                                                docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 1.45kB                                                                             0.0s
 => WARN: JSONArgsRecommended: JSON arguments recommended for ENTRYPOINT to prevent unintended behavior related t  0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                   0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/8] FROM docker.io/library/ubuntu:latest                                                                     0.0s
 => [internal] load build context                                                                                  0.1s
 => => transferring context: 296B                                                                                  0.0s
 => [2/8] RUN echo "deb http://mirrors.aliyun.com/ubuntu noble main restricted universe multiverse" > /etc/apt/so  0.3s
 => [3/8] RUN apt update                                                                                          26.5s
 => [4/8] RUN DEBIAN_FRONTEND=noninteractive apt install -y python3                                                8.5s
 => [5/8] RUN apt install -y python3-pip                                                                          30.7s
 => [6/8] RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/                              0.4s
 => [7/8] RUN pip install flask --break-system-packages                                                            1.7s
 => [8/8] COPY app.py opt/app.py                                                                                   0.0s
 => exporting to image                                                                                             0.9s
 => => exporting layers                                                                                            0.9s
 => => writing image sha256:7b90f5f4ba4060d56f2c34ba2899d8edc4e58ca5f9b127352dc050a769dc6642                       0.0s
 => => naming to docker.io/library/docker-flask-simple

View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/4vvkza3ieqprmuldajybj7v75

 1 warning found (use docker --debug to expand):
 - JSONArgsRecommended: JSON arguments recommended for ENTRYPOINT to prevent unintended behavior related to OS signals (line 26)

现在你可以在 docker-desktop 中看到这个构建好的镜像。

运行容器

cmd
X:\docker-flask>docker run docker-flask-simple
 * Serving Flask app 'opt/app.py'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.17.0.2:5000
Press CTRL+C to quit

可以通过映射端口运行容器,现在,可以在宿主机上访问 8888 端口,路由到容器内的 5000 端口,浏览器访问 http://127.0.0.1:8888/how are you 或另一个路由即可得到响应:

cmd
X:\docker-flask>docker run -p 8888:5000 docker-flask-simple
 * Serving Flask app 'opt/app.py'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.17.0.2:5000
Press CTRL+C to quit
172.17.0.1 - - [11/Jan/2025 14:32:38] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [11/Jan/2025 14:32:39] "GET /favicon.ico HTTP/1.1" 404 -
172.17.0.1 - - [11/Jan/2025 14:32:48] "GET /how%20are%20you HTTP/1.1" 200 -

发布镜像

制作好的镜像可以发布到自己的 docker 账户中,若设置为公开,世界上所有地方都可以拉取该容器。

制作含有个人账户标签的镜像: docker build . -t your_docker_username/docker-flask-simple

由于已经制作过该镜像,因此该指令使用缓存,将很快完成。使用 docker images 查看当前拥有的镜像。

登录 docker:

cmd
X:\docker-flask>docker login
Failed to start web-based login - falling back to command line login...

Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.
You can log in with your password or a Personal Access Token (PAT). Using a limited-scope PAT grants better security and is required for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/

Username: your_docker_username
Password:

Login Succeeded

发布 docker 镜像:

cmd
X:\docker-flask>docker push your_docker_username/docker-flask-simple
Using default tag: latest
The push refers to repository [docker.io/your_docker_username/docker-flask-simple]
04cd41c9d278: Pushed
310ac756ce9d: Pushed
da6d820b211f: Pushed
b6bb980bb5d2: Pushed
312a73db7277: Pushed
c63bce107a6e: Pushed
54594419d902: Pushed
687d50f2f6a6: Pushed
latest: digest: sha256:e72b0d7c0c8b98ec125f71464bffd020ae880c3efebb38467241c789a2080f9a size: 1998

现在,你可以在 docker hub 的账户中看到这个镜像。