如何在 Podman 上将本地机器的卷挂载上去

22

我想使用Podman进行本地开发。我的想法是使用本地文件夹并将其与容器同步,以便在容器中运行我的应用程序。

我发现,如果我在使用Docker时使用的-v选项,可以在服务器机器上使用,正如文档中所说的-v Bind mount a volume into the container. Volume src will be on the server machine, not the client。因此,当我使用该选项时,文件夹未被挂载,并且我无法通过podman exec -it application bash访问它。

有没有办法解决这个问题? 我想要类似于以下命令的功能:

docker run -v localFolder:/remoteFolder application

其中localFolder是我本地机器上的路径,将映射到容器中的remoteFolder

6个回答

28
podman machine stop podman-machine-default
podman machine rm podman-machine-default

podman machine init -v $HOME:$HOME
podman machine start

podman run -ti --rm -v $HOME:$HOME busybox

为什么不像我在 https://dev59.com/SFEG5IYBdhLWcg3wQoRw#71882521 中所做的那样使用 init -v ${HOME}:${HOME} 呢?有任何安全隐患吗? - Andrei
我认为这不起作用:您没有权限。不确定是否更改。如果podman支持它,我很想使用这种方式。 - zhigang
在我的 macOS 上运行良好。目前无法测试其他操作系统,所以不确定。 - Andrei
2
刚刚测试过了,没错它可以用。不明白为什么官方的 Podman 机器初始化手册说: 默认操作系统中,根文件系统以只读方式挂载,因此必须在 /mnt 目录下创建挂载点。 https://docs.podman.io/en/latest/markdown/podman-machine-init.1.html 或许是时间改变了一些东西。谢谢 @Andrei! 我已经更新了回答。 - zhigang
一个很好的例子来验证这一点:https://medium.com/@butkovic/favoring-podman-over-docker-desktop-33368e031ba0 - prayagupa
谢谢!这个修复了我在Mac上的“Error: statfs xxx no such file or directory”问题。现在“podman-compose”成功运行了。 - haolianglearn

6

在运行 podman machine init 命令之前,需要确保先将卷挂载到 podman 机器上。

假设我们感兴趣的是:

  • 将 $HOME 目录(或其任何子目录)挂载到容器中的选项,
  • 为 podman 机器保留 4 个 CPU、60GB 的磁盘空间和 6GB 内存。

使用以下命令创建 podman 机器:

podman machine init --cpus=4 --disk-size=60 --memory=6096 -v $HOME:$HOME

然后启动它:

podman machine start

为了看它是否运行,让我们使用:

podman machine ls

让我们先运行一个(ubuntu)容器,不进行挂载并查看 /opt 目录中有什么:

podman run ubuntu ls /opt

没有输出表示容器中的/opt目录为空。

现在让我们尝试使用卷挂载选项:

mkdir test-dir
touch test-dir/test-file.txt
podman run -v ./test-dir:/opt ubuntu ls /opt
test-file.txt

我们可以看到挂载的目录及其内容现在可以在容器中访问!
(摘自: https://medium.com/@butkovic/favoring-podman-over-docker-desktop-33368e031ba0

5
如果您使用的是Windows操作系统,且已经安装了WSL(Windows子系统),则可以在不需要删除和重新初始化podman-machine-default的情况下创建一个卷。
首先,使用WSL连接到podman机器:
wsl -d podman-machine-default

然后执行以下命令:

[root@COMPUTER ~]# podman volume create myVolume
myVolume
[root@COMPUTER ~]# podman volume mount myVolume
/var/lib/containers/storage/volumes/myVolume/_data

现在要与容器共享文件,请将它们从WSL挂载点复制到卷挂载点:
[root@COMPUTER ~]# cp /mnt/c/users/myname/myfolder/*.* /var/lib/containers/storage/volumes/myVolume/_data

最后,您可以将一个卷挂载到容器中以访问这些文件。退出wsl并运行:
podman run --rm -v myVolume:/remoteFolder -t docker.io/bash ls /remoteFolder

注意,参数的顺序很重要


3
迭代 @zhigang 的回答:
podman machine stop podman-machine-default || true
podman machine rm podman-machine-default --force || true
podman machine init -v "$(pwd):$(pwd)"
podman machine start

现在,docker-compose / podman-compose 只与它们的配置文件一起工作。
version: '3.9'  # needed for PyCharm to work
services:
  app:
    image: python:alpine
    working_dir: /app/
    volumes: [.:/app/]

$ podman-compose run --rm app venv/bin/python main.py

从podman 4.1.1开始,-v $HOME:$HOME会自动挂载到默认的“init”命令中。 - Larry Cai

0

检查一下2022年2月发布的podman 4.0.0(以及类似于4.0.2的最新版本)是否有帮助。

仍然存在一些错误(例如问题13548),但是这个想法是:

10379 "共享卷,就像Kubernetes Pod中的"问题已经通过PR 11409得到解决。

Pod Volumes Support

新增对使用新基础设施容器设计的 Pod 中 --volume 标志的支持。
用户可以像普通容器一样指定所有卷选项。

指定 --volume 标志会导致基础设施容器填充指定的挂载点。
然后,加入 Pod 的所有容器都有一个 VolumesFrom 容器,从而继承这些挂载点。

文档中提到:

创建一个绑定挂载点。 如果您指定了 -v /HOST-DIR:/CONTAINER-DIR,Podman 将会将主机中的 /HOST-DIR 绑定挂载到 Podman 容器中的 /CONTAINER-DIR。 同样地,-v SOURCE-VOLUME:/CONTAINER-DIR 将会将主机中的卷挂载到容器中。 如果没有这样的命名卷存在,Podman 将会创建一个。

注意:问题13548已经通过PR 13594和{{link2:cdoern/podman 提交7a53428}}(2022年4月)得到解决。

修复pod卷传递并更改基础结构继承

基础结构Inherit函数未正确传递pod卷信息给新容器。

修改inherit函数和结构以使用克隆选择中使用的新的ConfigToSpec函数从临时规范中选择适当的实体,并在spegen端验证它们,而不是直接传递到配置。


在解决所有问题之前,Dmitry Kankalovich评论中提到:

目前(2022年4月),我采用了一个解决方法,在机器初始化时挂载卷:podman machine init -v ./data:/mnt/data 这并不是很灵活,但可以让事情开始运转。


1
我本来希望它能够工作,但是没有。我已经将podman更新到4.0.2并重新创建了虚拟机,但仍然出现相同的错误。也许我应该强制使用最新的qemu虚拟机,如果那是问题的话。 - Dmitry Kankalovich
@DmitryKankalovich 或许可以创建一个新的问题,引用 https://github.com/containers/podman/issues/10379?你的使用情况需要进行调查。 - VonC
谢谢,我会看一下的。目前我采用了一个解决方法,在机器初始化时挂载卷 podman machine init -v ./data:/mnt/data,这并不是很灵活,但可以让事情开始运转。 - Dmitry Kankalovich
@DmitryKankalovich 好的,谢谢您的反馈。我已经在答案中包含了您的评论。 - VonC

-3
我建议使用--mount标志而不是-v--volume。我假设您想在容器中运行应用程序时轻松修改主机上的文件。以下是一个快速示例:
首先,目录需要存在于主机上:
user@host:~$ mkdir ~/localFolder

~/localFolder目录中创建一个带有一些文本的文件:
user@host:~$ echo "Sample Text" > ~/localFolder/test

接下来,使用绑定挂载启动容器。此示例使用一个非特权用户的Podman无根容器,并使用Debian Bullseye镜像。注意:最佳实践是对源(主机)和目标(容器)目录都使用绝对路径:

user@host:~$ podman run -it --rm --mount type=bind,source=/home/$USER/localFolder,target=/remoteFolder docker.io/debian:bullseye /bin/bash

现在你的~/localFolder目录将作为/remoteFolder在容器内部访问:
root@f724a0337f76:/# cat /remoteFolder/test 
Sample Text

您可以在不重启容器的情况下添加新文件或修改此文件夹中的现有文件。

Docker在这里提供了关于绑定挂载的详细解释:https://docs.docker.com/storage/bind-mounts/


1
我很抱歉,我仍然遇到一个错误,如Error: statfs ~/localFolder: no such file or directory - Carabes
你在容器内还是主机上遇到了那个错误? - muncherelli
1
当Podman在使用虚拟机(例如在Mac上)时,我们需要先将主机挂载到虚拟机中,然后再从虚拟机中挂载到容器中。不幸的是,这里涉及到3个层面。 - Gaetan
1
这个错误应该是在容器里面(主机上有那个文件)。那么,我该如何将主机挂载到虚拟机中呢? - Carabes
3
错误是来自虚拟机上的Podman,容器从未启动。这里是相关功能请求。 - Bracken
同意@Bracken的观点,我还没有发现-v在podman方面像docker那样工作。希望它能尽快实现。 - Tuhin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接