介绍

什么是Docker

Docker 是一个开源的容器化平台,用于自动化应用程序的部署。它包装软件及其依赖项到一个标准化的单元中,用于软件开发。使用 Docker 的主要场景包括:

  • 应用程序的打包和部署:当您需要在不同的环境中一致地部署应用程序时,Docker 是一个理想的选择。它通过容器来确保应用程序在不同的系统和平台上表现一致。
  • 微服务架构:对于采用微服务架构的系统,Docker 提供了隔离、快速部署和伸缩性,非常适合于管理和部署微服务。
  • CI/CD 流程:Docker 可以很好地集成到持续集成和持续部署(CI/CD)的流程中,实现自动化测试和部署。

为什么用Docker?

  • Docker提供了更高级别的隔离(操作系统级别),而 Conda 提供了较低级别(Python/R 环境级别)的隔离。
  • Docker 适合部署一些深度学习环境。
    • 服务器CUDA版本不允许升级或降级时,使用Docker可以解决。只要宿主机的 NVIDIA 驱动与容器内部的 CUDA 版本兼容即可正常运行使用GPU的docker容器。
    • 思路:在Windows上搭建基础镜像,连进容器配置环境,通过docker commit保存镜像,再通过docker save导出,迁移到服务器上。
  • 有些应用需要在Docker部署,比如coffee AI。
  • 网络问题,有了镜像就可以共享给其他人,不需要其他人再下载。

容器和镜像

  • 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样。
  • 镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

Dockerfile

Docker 可以通过读取 Dockerfile创建一个镜像,Dockerfile 是一个文本文档,其中包含用户可以在命令行上调用和组合镜像的所有命令。
Dockerfile常见命令:

  • FROM:Dockerfile必须从From开始,它为容器设置最基础的镜像
  • WORKDIR:我们的工作目录,为后面的RUN等指令设置工作目录
  • RUN:运行指令
  • COPY:把Dockerfile所在目录的一些文件拷贝到工作空间
  • EXPOSE:容器在运行时侦听的端口,它只是声明容器运行时需要监听的端口号,需要使用 docker run 命令的 -p 参数来将容器端口映射到宿主机上。比如-p 8080:80,表示将容器的 80 端口映射到宿主机的 8080 端口上。
  • HEALTHCHECK:告诉 Docker 如何测试容器以检查它是否仍在工作
  • ENTRYPOINT:配置容器,里面包括了可以run的py文件,也包括了run指令,可以让容器创建时去运行某些指令

写Dockerfile的注意事项,随时补充

  1. From的镜像可以选择更基础的镜像。
  2. pip 后面增加 –no-cache-dir,减少缓存。
  3. 在同一个RUN里不同的命令经常用 && 来连接这是一种常见的做法,主要有以下几个原因:
  4. 减少图层: Dockerfile 中的每个 RUN 指令都会创建一个新的图层。通过使用 && 将多个命令连接在一起,可以减少生成的图层的数量。这样做的好处是创建更小、更简洁的镜像,并且可能提高构建速度。
  5. 确保所有命令都成功执行: 当使用 && 时,如果一个命令失败(返回非零退出状态),整个 RUN 指令将失败并停止执行。这意味着如果 apt update 失败,紧随其后的 apt install 不会执行。这是一种保护措施,以确保不会在部分更新的或不一致的状态下构建镜像。
  6. 清洁和优化: 通过在一个 RUN 指令中连接多个命令,您可以在完成必要的安装和配置后立即进行清理(例如,删除临时文件或清除缓存)。这有助于保持镜像的大小尽可能小。
  7. apt install 后面 rm -rf /var/lib/apt/lists/*。

常用命令

查看docker所有命令

1
docker commond --help

镜像操作

查看docker所有镜像

1
docker images

下载镜像,Tag表示版本,有些镜像的版本显示latest,为最新版本

1
docker pull 镜像名:TAG

删除镜像

1
docker rmi 镜像名:TAG

使用国内源来拉取镜像,将registry.docker-cn.com填写到镜像名前。

  1. Docker中国区官方镜像:https://registry.docker-cn.com
  2. 网易:http://hub-mirror.c.163.com
  3. ustc:https://docker.mirrors.ustc.edu.cn
  4. 中国科技大学:https://docker.mirrors.ustc.edu.cn
  5. 阿里云容器 生成自己的加速地址:登录:cr.console.aliyun.com
    windows 可以直接在设置里填入加速的地址。
1
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}

图片

获取镜像的元信息,获取镜像的详细信息,包括存放地址等等

1
docker inspect 镜像名:TAG

从本地的压缩包里导入镜像

1
docker load -i 压缩包名

或者

1
docker load < 压缩包所在路径

使用Dockerfile构建镜像,.表示Dockerfile所在路径,-t表示镜像名和TAG

1
docker build -t 镜像名:TAG .

如果 Dockerfile 文件不在当前目录中,或者 Dockerfile 文件的名称不是 Dockerfile,则可以使用 -f 参数来指定 Dockerfile 文件的路径和名称。

容器操作

运行容器

1
docker run --name 容器名 -i -t -p 主机端口:容器端口 -d -v 主机目录:容器目录:ro 镜像ID或镜像名:TAG
  • -i:表示以交互模式运行容器
  • -t:表示分配一个伪终端
  • -p:表示将主机的端口映射到容器的端口
  • -d:表示容器运行后处于后台
  • -v:表示挂载主机目录到容器目录,ro表示只读
  • –name:表示容器名
  • 镜像ID或镜像名:TAG:表示镜像名和TAG

容器列表

1
docker ps -a -q
  • docker ps查看正在运行的容器
  • -a 查看所有容器(运行中、未运行)
  • -q 只查看容器的ID
  • -as 查看容器占用存储空间
    启动容器
    1
    docker start 容器ID
    停止容器
    1
    docker stop 容器ID
    删除容器
    1
    docker rm -f 容器ID或容器名
  • -f 表示强制删除
  • -v 表示删除容器时删除挂载的卷
  • -a 表示删除所有容器
  • -l 表示删除容器时删除关联的链接
  • -p 表示删除容器时删除关联的端口
  • -s 表示删除容器时删除关联的网络
  • -t 表示删除容器时删除关联的定时任务
  • -u 表示删除容器时删除关联的用户
  • -w 表示删除容器时删除关联的网络
    1
    docker container prune # 删除所有没有运行的容器,谨慎操作
    进入运行容器
    1
    docker exec -it 容器ID /bin/bash
  • 进入正在运行的容器并且开启交互模式终端
  • /bin/bash是固有写法,作用是因为docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动
    bash。
  • 也可以用docker exec在运行中的容器执行命令

查看容器使用的资源

1
docker stats 命令会每隔 1 秒钟刷新一次输出的内容直到按下 ctrl + c

输出的主要内容:

  • [CONTAINER]:以短格式显示容器的 ID。
  • [NAME]:容器名称
  • [CPU %]:CPU 的使用情况。
  • [MEM USAGE / LIMIT]:当前使用的内存和最大可以使用的内存。
  • [MEM %]:以百分比的形式显示内存使用情况。
  • [NET I/O]:网络 I/O 数据。
  • [BLOCK I/O]:磁盘 I/O 数据。
  • [PIDS]:PID 号。
    1
    2
    docker stats
    docker stats --no-stream # 只显示一次资源情况,不实时跟踪

制作Docker镜像

两种方式,一种是根据已有镜像使用docker commit构建,另一种是根据已有镜像使用Dockerfile构建。

根据已有镜像使用docker commit构建

这一方法的核心是docker commit

  • docker commit可以从容器创建一个新的镜像。
  • 通过对运行中的容器进行更改,然后使用 docker commit 命令,可以将容器的当前状态保存为新镜像。
  • 这种方法适用于快速的实验,但不推荐用于生产环境,因为:
    • docker commit不会明确记录构建过程,缺乏可重复性和透明性,会产生所谓的黑箱镜像。
    • 在容器中执行命令,会有很多文件被改动或添加。安装软件包、编译构建,那会有大量的无关内容被添加进来,将会导致镜像极为臃肿。
    • 简单的Python训练环境,可以用这个方法图方便,快速构建镜像。
      思路:
  1. 先拉取已有的镜像。
  2. 使用镜像运行容器后,在容器内安装项目需要的Python依赖。
  3. 将整个容器通过docker commit指令制作成镜像。
  4. 导出镜像,在服务器上导入。

拉取已有镜像

官方Pytorch镜像:https://github.com/pytorch/pytorch#docker-image
也可以从docker hub里找到官方Pytorch镜像:https://hub.docker.com/r/pytorch/pytorch/tags
https://hub.docker.com/r/pytorch/pytorch/tags
图片
同样的pytorch和cuda版本会有两种镜像,分别是devel和runtime镜像,区别如下:
devel 镜像:

  • 用途:devel(开发)镜像包含了编译和运行 CUDA 应用所需的所有依赖,包括编译器和开发工具。
  • 适用场景:如果您需要编译使用 CUDA 的自定义操作或者需要编译整个 PyTorch 源代码,那么 devel 镜像是必需的。
  • 大小:由于包含更多的开发工具和库,devel 镜像通常比 runtime 镜像大很多。
    runtime 镜像:
  • 用途:runtime(运行时)镜像仅包含运行基于 CUDA 的应用程序所必需的库和工具。
  • 适用场景:如果您只需要运行已经编译好的 CUDA 应用程序,而不需要进行额外的编译或开发工作,runtime 镜像就足够了。
  • 大小:相较于 devel 镜像,runtime 镜像更小,因为它不包含额外的编译工具和库。
    我们也可以用其他人发布的可靠的镜像:https://github.com/cnstark/pytorch-docker
    这里我选择的镜像是:cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04,它包括了一个ubuntu22.04操作系统,python3.10,gpu版本的pytorch2.0.1和cuda11.8。
    图片
    拉取镜像
    1
    docker pull cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04
    通过docker images可以看到,已经成功拉取了镜像。
    图片
    介绍镜像的网址一般会给出使用的方法,也就是创建容器的参数,我使用了cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04这个镜像,它的用法和pytorch给的docker容器是一样的。
    图片
    即:
    1
    2
    3
    4
    5
    6
    docker run -it --rm \
    --gpus all \
    --net host
    -v /path/to/project:/path/to/project \
    -v /path/to/dataset:/path/to/dataset \
    cnstark/pytorch:[TAG]

运行容器

在Windows系统的Windows PowerShell中,用反引号`表示换行。如果要在命令行中使用反斜杠\来进行换行,需要在\字符后面再加上一个空格,否则反斜杠\就会被解释为一个转义字符。

1
2
3
4
5
docker run -it --rm `
--gpus all `
--net host `
-v E:/Project/Diffusion/DiffTraj-main:/app `
cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04

Ubuntu系统,使用反斜杠\进行换行,使用下面的命令:

1
2
3
4
5
docker run -it --rm \
--gpus all \
--net host
-v E:/Project/Diffusion/DiffTraj-main:/app \
cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04

这些参数很重要!!!

  • -it:前台运行容器,关了终端就关闭容器了。这个参数表示启用交互式终端,也就是让您能够与容器进行交互。-i表示交互式,-t表示分配一个伪终端。
  • -dit:后台运行容器,并启用交互式终端,也就是让您能够与容器进行交互。-d表示后台运行,-i表示交互式,-t表示分配一个伪终端。
  • –rm:这个参数表示容器退出后自动删除容器文件系统,这样可以防止容器文件系统占用过多的磁盘空间。
    • 在Docker容器退出时,默认容器内部的文件系统仍然被保留,以方便调试并保留用户数据。
    • 在Docker Desktop里暂停掉–rm的容器后,会自动把这个容器删除,所以有时候可以不加上。
  • –gpus all:这个参数表示将所有的GPU都分配给容器使用。这个参数需要在安装了NVIDIA驱动和Docker的情况下才能生效。
  • –net host:这个参数表示容器将使用主机网络,这意味着容器将与主机共享网络命名空间,可以访问主机上的网络设备和服务。
  • -v E:/Project/Diffusion/DiffTraj-main:/app:这个参数表示将主机上的E:/Project/Diffusion/DiffTraj-main目录挂载到容器内的/app目录中,这样容器就可以访问主机上的这个目录。
  • cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04:这个参数表示要使用的Docker镜像的名称和标签。在这个例子中,使用的是cnstark/pytorch镜像的2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04标签,这个镜像包含了PyTorch深度学习框架和CUDA工具包,可以在容器中运行深度学习任务。
    如果之后项目里的文件比较多,建议使用挂载的方式,挂载可以让容器和宿主机共享数据。当你将宿主机上的目录或文件挂载到容器中时,容器中的该目录或文件就会和宿主机上的目录或文件保持同步,它们之间的修改都会相互影响。
    执行好docker run后,可以看到,我们已经运行了容器并且启动了交互式终端。

执行好docker run后,可以看到,我们已经运行了容器并且启动了交互式终端。
图片
如果我们进入app目录,会看到我们的项目已经被成功挂载了。
图片
我们输入pip list和python –version,可以看到这个容器已经安装了py3.10.11-cuda11.8.0。
图片

安装依赖

我们拉取的镜像里只包含了最纯净的pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04,根据我们要部署的应用,可能还需要有一些依赖包需要我们手动安装。
我们可以写一个或者生成一个requirement.txt用于安装我们项目需要的其他依赖,我在目录里创建一个requirement.txt后,可以看到app目录也会有这个文件,这就是挂载的含义。

1
2
colored==2.2.4
matplotlib==3.8.0

图片
这里我用pip补充安装了两个包colored==2.2.4和matplotlib==3.8.0。
图片

导出镜像

先不关闭原来的docker终端,另外新建一个终端,通过docker ps可以看到我们的容器正在运行,容器的ID是a563dee1debf。
图片
接着我们使用docker commit命令去创建一个镜像:

1
docker commit CONTAINER ID REPOSITORY:TAG
  • CONTAINER ID表示容器ID,通过docker ps查询
  • REPOSITORY:TAG表示生成的容器名和标签,可以任意命名
    这里我使用如下命令:
    1
    docker commit a563dee1debf difftraj:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04
    通过docker images可以看到,已经创建了这个镜像。
    图片
    我们可以根据这个镜像创建一个容器进行验证
    1
    2
    3
    4
    5
    docker run -it --rm `
    --gpus all `
    --net host `
    -v E:/Project/Diffusion/DiffTraj-main:/app `
    difftraj:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04
    直接python main.py,发现可以运行,说明在这个镜像里已经把训练模型需要的包安装好了。
    图片

打包镜像

我们使用docker save命令保存镜像,在Ubuntu中,可以使用gzip进行压缩:

1
docker save REPOSITORY:TAG |gzip > 镜像名

这里使用命令:

1
docker save difftraj:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04 |gzip > difftraj_images.tar.gz

如果在windows中,可以使用下面的命令,修改成自己的路径,导出可能要一两分钟。这里将镜像名设置为difftraj_image.tar,并保存到E:\Project\Diffusion\DiffTraj-main目录。
如果要导出到windows上进行导入,后缀可以用tar,如果要导出到linux上进行导入,后缀可以用tar.gz

1
docker save difftraj:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04 -o E:\Project\Diffusion\DiffTraj-main\difftraj_image.tar

注意导出镜像的时候,用使用镜像的名字和TAG,不要用镜像ID,否则在导入镜像的时候,镜像的名字和TAG都会为空,需要重新命名,重新命名命令如下:

1
docker tag [镜像id] [新镜像名称]:[新镜像标签]

图片

导入镜像

Ubuntu使用如下命令:

1
docker load < 压缩包所在路径

Windows使用如下命令:

1
docker load -i 压缩包所在路径

根据已有镜像使用Dockerfile构建

这一方法的核心是创建Dockerfile

  • 使用Dockerfile创建镜像是比较标准的流程,推荐使用这种方法
    • Dockerfile里面的一些命令。
    • Docker创建镜像时的上下文含义。
      思路:
  1. 先创建Dockerfile,使用From命令选择基于什么镜像。
  2. 根据自己的需求,在Dockerfile里使用RUN命令安装各种依赖。
  3. 使用docker build创建镜像。
  4. 使用docker run创建容器。运行一下代码,测试镜像里的依赖是否满足项目的要求,如果还缺少依赖,则回到第二步,在Dockerfile里使用RUN补充安装依赖。
  5. 导出镜像,在服务器上导入。

创建Dockerfile

在使用Dockerfile构建镜像时,由于Docker的原理,我们一般会将 Dockerfile 置于一个空目录下,或者项目的根目录下。
这里以轨迹扩散模型的项目为例子,完整的Dockerfile如下,我们用到了 FROM WORKDIR COPY 和 RUN 这四个命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04

WORKDIR /app

COPY requirements.txt /app

RUN pip install --no-cache-dir -r requirements.txt

# (可选)复制当前目录下的其他文件到容器的 /app 目录
COPY . /app

# (可选)设置容器启动时执行的命令
CMD ["python", "your_script.py"]

From命令:Dockerfile必备的第一条指令,指定基础镜像,可以是服务类的镜像nginx、redis、mongo、mysql、httpd、php、tomcat,也可以是操作系统镜像ubuntu、debian、centos、fedora、alpine。

From命令如果选择了很大的基础镜像,那最后制作的docker镜像占的空间也会很大。

1
FROM cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04

WORKDIR命令:设置后续指令的工作目录,一般写在COPY和RUN前面。
然后通过WORKDIR命令,确定工作目录。

1
WORKDIR /app

COPY命令:将文件复制到镜像的指定目录中中。
接着通过COPY命令,将复制requirements.txt到镜像里的工作目录/app。

1
COPY requirements.txt /app

RUN命令:RUN命令可以像Shell脚本一样执行命令,后面的内容和直接在命令行中输入的命令是一样的。
最后通过RUN命令,执行pip命令,安装Python项目的依赖。

1
RUN pip install --no-cache-dir -r requirements.txt

我们也可以这么写,直接用RUN去执行pip命令安装我们需要的包。

1
2
3
4
5
6
7
8
# 使用 cnstark/pytorch 镜像作为基础镜像
FROM cnstark/pytorch:2.0.1-py3.10.11-cuda11.8.0-ubuntu22.04

# 设置工作目录
WORKDIR /app

# 使用 pip 安装所需的包
RUN pip install --no-cache-dir colored==2.2.4 matplotlib==3.8.0

创建镜像

理解 docker build 的工作原理

  • Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。
  • 因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
  • 当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?
  • 这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

使用docker build命令,基于Dockerfile构建镜像。

1
docker build -t test:v1.0 .
  • 最后这个点号表示Docker 镜像构建的上下文(Context),就在当前Dockerfile所在的目录。
  • 也就是表示,构建这个镜像需要的所有文件,都在这个目录,比如这里的requirements.txt。
  • COPY 这类指令中的源文件的路径都是相对路径,所以我们应该把构建镜像需要的文件都复制到上下文目录中。
    图片

打包镜像

最后使用docker save打包镜像即可,见3.1.5。

使用Dockerfile从0开始构建

创建Dockerfile

Difftraj镜像,指定版本的 PyTorch、Python、CUDA 以及 colored==2.2.4 和 matplotlib==3.8.0。

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 使用 Ubuntu 22.04 作为基础镜像
FROM ubuntu:22.04

# 设置非交互式安装,避免在安装过程中出现提示
ENV DEBIAN_FRONTEND=noninteractive

# 更新软件源并安装 Python 3.10 和 pip
RUN apt-get update && apt-get install -y \
python3.10 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*

# 设置 Python 3.10 为默认的 Python 版本
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1

# 安装 CUDA 11.8.0(这里假设您需要的是 CUDA Toolkit,而不是完整的 NVIDIA 驱动)
# 这里需要找到合适的 CUDA Toolkit 11.8.0 的安装方法,以下仅为示例
RUN apt-get update && apt-get install -y \
software-properties-common \
&& add-apt-repository ppa:graphics-drivers/ppa \
&& apt-get update \
&& apt-get install -y cuda-toolkit-11-8 \
&& rm -rf /var/lib/apt/lists/*

# 安装 PyTorch 2.0.1(确保这个版本与您的 CUDA 版本兼容)
RUN pip install torch==2.0.1+cu118 -f https://download.pytorch.org/whl/torch_stable.html

# 安装其他必要的 Python 包
RUN pip install colored==2.2.4 matplotlib==3.8.0

# 设置工作目录
WORKDIR /app

# 复制应用代码到工作目录
COPY . /app

# 镜像构建完成后的默认命令
CMD ["python", "your_script.py"]

# 设置标签
LABEL maintainer="yourname@example.com"

下面这个是Steamlit官方用Docker安装教程里给出的Dockerfile,这个Dockerfile安装了git,又从git上clone了streamlit的一个demo。
# /app

FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
build-essential \
curl \
software-properties-common \
git \
&& rm -rf /var/lib/apt/lists/*

RUN git clone https://github.com/streamlit/streamlit-example.git .

RUN pip3 install -r requirements.txt

EXPOSE 8501

HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health

ENTRYPOINT ["streamlit", "run", "streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]

创建镜像

在建立好Dockerfile文件后,使用docker build创建镜像,再使用docker run创建容器。

  1. docker build 会根据你写的dockerfile文件创建镜像。
  2. docker run 会根据你创建好的镜像运行容器。

创建镜像,-t 表示指定镜像名称为streamlit,-f表示指定目录的Dockfile,这里用的是绝对路径。

1
docker build -f /home/streamlit/Dockerfile -t streamlit .

创建容器

运行镜像,-p 表示宿主机占用的端口,-v 表示挂载两个目录,–name 表示指定容器名字,方便后续停止,-d表示将容器挂载到后台运行

1
docker run -p 8501:8501 -v /home/streamlit:/app --name streamlit -d streamlit

浏览器里输入 http://你的服务器IP地址:8501/,即可进入streamlit应用界面,部署完成。
如果之后项目里的文件比较多,建议使用挂载的方式,挂载可以让容器和宿主机共享数据。当你将宿主机上的目录或文件挂载到容器中时,容器中的该目录或文件就会和宿主机上的目录或文件保持同步,它们之间的修改都会相互影响。
比如之后要把镜像里的/app/目录挂载到到硬盘的某个目录,比如/home/streamlit目录,使用 -v 参数即可。这样就不需要在Dockerfile文件里使用COPY命令了。在其中一个目录的修改会影响到另一个目录的修改。

1
docker run -p 8501:8501 -v /home/streamlit:/app -d streamlit 

注意事项(更新ing)

Docker build 缓存机制

在 docker build 的过程中,Docker 会缓存每一步构建的结果。也就是说,如果你重新执行 docker build 命令时,Docker 会尝试使用缓存来加速构建过程。
Docker 缓存的工作原理:每个 Dockerfile 指令(如 FROM, COPY, RUN 等)都会创建一个新的层,Docker 会缓存每个层的结果。如果 docker build 过程中某个层的指令及内容没有变化,Docker 就会跳过这一步,并使用缓存的层。

  1. 确保 Docker 重新复制了修改后的文件
    为了强制 Docker 在构建时重新复制修改后的文件,你可以通过以下几种方法解决缓存问题:
    方法一:使用 –no-cache 标志: 你可以在构建镜像时使用 –no-cache 参数来禁用 Docker 的缓存机制。这会强制 Docker 重新执行所有步骤,包括复制文件、安装依赖等。
    1
    docker build --no-cache -t {name} .
    方法二:手动修改 Dockerfile 来破坏缓存: 另一种方法是通过修改 Dockerfile 的某些部分来强制 Docker 重新构建相关的层。例如,如果你修改了代码文件,并且 COPY 指令复制了这些文件,你可以通过修改 Dockerfile 中相关步骤的顺序或其他内容来“破坏”缓存。
    比如,将 COPY 指令移动到 Dockerfile 的最后,或者在 COPY 之前做一个小的修改(如添加一个临时的 RUN 命令),这样 Docker 会认为该步骤有了变化,并重新执行复制文件的操作。
    1
    2
    3
    4
    5
    # 先执行其他操作
    RUN echo "Temporary change to break cache"

    # 再复制修改后的文件
    COPY . /app
    这样,COPY 指令就不会被缓存,因为 Docker 认为文件发生了变化。
  2. 重新启动容器时确保使用最新的镜像
    确保在执行 docker run 启动容器时使用的是你刚刚构建的最新镜像。特别是,如果你有多个版本的镜像,可能会不小心启动旧的镜像。
    可以通过以下命令确保使用最新构建的镜像:
    1
    docker run -p 5000:5000 --rm {name}
  • –rm:这个选项会在容器停止后自动删除容器,避免你重复使用旧容器。
  • imagemagick:确保这指向你最新构建的镜像。

参考文档:

Docker build 网络问题1

如果你利用docker build执行Dockerfile创建镜像时,在第一行命令,例如FROM python:3.9,就遇到了网络错误。但是你检查你的网络连接并没有问题的话,你可以先执行docker pull python:3.9命令拉去基础镜像,然后执行docker build命令继续创建Dockerfile的镜像。(具体原因没搞明白。)