如何使用Docker让主机和容器读写相同的文件?

9 浏览
0 Comments

如何使用Docker让主机和容器读写相同的文件?

我想将Docker容器中的一个目录与我的工作站进行卷挂载,这样当我从工作站编辑卷挂载的内容时,容器中的内容也会更新。这对于一般的测试和开发Web应用程序非常有用。\n然而,我在容器中遇到了权限被拒绝的问题,因为容器和主机的UID不同。难道Docker的初衷不是让开发更快更容易吗?\n这个答案解决了我在将Docker容器挂载到工作站时遇到的问题。但是通过这样做,我会对容器进行更改,而这些更改在生产环境中是不需要的,这违背了在开发过程中使用Docker的初衷。\n容器是Alpine Linux,工作站是Fedora 29,编辑器是Atom。\n问题\n是否有另一种方法,使得我的工作站和容器都可以读写相同的文件?

0
0 Comments

问题原因:在Docker中,主机和容器默认情况下是相互隔离的,无法直接读写相同的文件。这是因为容器中的用户ID(UID)在容器定义中是固定的,而主机系统中的用户ID是不同的,导致无法直接访问相同的文件。

解决方法1:在主机系统中创建一个和容器中的机器UID和GID相同的用户账户,然后切换到该用户账户,对文件进行修改。由于主机操作系统认为是用户自己在访问自己的文件,不会出现错误,而容器操作系统也会看到相同的修改。

解决方法2:作为替代方案,可以考虑以root身份进行文件编辑。这样就可以直接读写相同的文件。

以下是上述内容的整理:

问题:如何使主机和容器能够读写相同的文件?

解决方法1:由于容器中的用户ID(UID)是固定的,可以在主机系统中创建一个与容器中的机器UID和GID相同的用户账户。然后切换到该用户账户,对文件进行修改。这样,主机操作系统会认为是用户自己在访问自己的文件,而容器操作系统也会看到相同的修改。

解决方法2:作为替代方案,可以考虑以root身份进行文件编辑,这样就可以直接读写相同的文件。

0
0 Comments

Docker是一种常用的容器化平台,它可以将应用程序及其依赖项打包成一个独立的容器,使得应用程序在不同的环境中都能够正常运行。然而,在使用Docker时,有时我们需要让容器和宿主机读写同一个文件,以实现数据共享或者文件传输等功能。本文将讨论如何实现在Docker中让主机和容器读写相同的文件。

问题的出现主要是因为绑定挂载(bind mounts)不包含任何UID映射功能,主机上的UID会在容器内部显示出来,反之亦然。如果这两个UID不匹配,就会导致读写文件时出现不同的UID,从而可能引发权限问题。

解决这个问题的方法有多种:

1. 使用Mac或在VirtualBox中部署Docker。这两种环境都具有文件系统集成功能,可以动态更新UID。对于Mac来说,这是通过OSXFS实现的。需要注意的是,这种方便性会带来性能损失。

2. 更改主机的UID。如果主机的UID与容器内部的UID匹配,就不会出现任何问题。只需在主机上的用户上运行usermod命令来更改UID,事情就会按照预期工作,至少在使用与容器内部不同UID的不同镜像时如此。

3. 更改镜像。一些人会将镜像修改为与其环境匹配的静态UID,通常是为了与生产环境中的UID匹配。其他人会在构建命令中传递一个构建参数,例如--build-arg UID=$(id -u),然后在Dockerfile中使用FROM alpine ARG UID=1000 RUN adduser -u ${UID} app等方式来进行构建。这种方法的缺点是每个开发人员可能需要一个不同的镜像,要么在每个工作站上进行本地构建,要么集中构建多个镜像,每个镜像都对应一个开发人员的UID。这两种方法都不是理想的选择。

4. 更改容器的UID。可以在compose文件中进行设置,或者使用docker run -u $(id -u) your_image命令为临时容器更改UID。然后,容器将以新的UID运行,并能够访问卷中的文件。然而,容器内部的用户名不一定与您的UID相匹配,这可能会导致容器内部运行的命令显示出奇怪的结果。更重要的是,容器内部由用户拥有但未被卷隐藏的任何文件都具有原始UID,可能无法访问。

5. 放弃,将所有内容都以root用户运行,或者将权限更改为777,允许所有人无限制访问目录。这种方法不符合生产环境中的运行方式,而且容器可能仍然以有限权限写入新文件,使得这些文件对容器外的用户来说是不可访问的。这也会带来以root用户运行代码的安全风险,或者让文件系统对主机上的任何用户都具有读写权限。

6. 设置一个动态更新容器的入口点。尽管不希望更改镜像,但这是我推荐的完整解决方案。容器需要以root身份启动,但仅在开发环境中,并且应用程序将以与生产环境匹配的用户身份运行。然而,入口点的第一步是将容器内的用户UID/GID更改为与卷的UID/GID匹配。这类似于选项4,但是现在镜像内部未被卷替换的文件具有正确的UID,并且容器内的用户现在显示的是更改后的UID,因此像ls这样的命令将显示容器内的用户名,而不是可能映射到另一个用户或根本没有用户的UID。虽然这是对镜像的更改,但代码只在开发环境中运行,并且只作为设置容器的短暂入口点,之后容器内的进程看起来与生产环境中的进程完全相同。

以上是解决在Docker中让主机和容器读写相同文件的几种方法及其原因的整理。每种方法都有其优缺点,具体选择取决于实际需求和环境条件。希望本文能对使用Docker进行文件读写的开发人员有所帮助。

0