gpt4 book ai didi

javascript - 我如何让主机和容器使用Docker读取/写入相同的文件?

转载 作者:行者123 更新时间:2023-12-02 19:58:25 25 4
gpt4 key购买 nike

我想将目录从Docker容器批量安装到我的工作站,因此当我从工作站编辑批量安装中的内容时,它也在容器中更新。通常,这对于测试和开发Web应用程序将非常有用。

但是我在容器中获得了拒绝权限,因为容器和主机中的UID不同。 Docker的最初目的不是应该使开发变得更快,更容易吗?

This answer解决了将Docker容器批量安装到我的工作站时遇到的问题。但是通过这样做,我对生产中不需要的容器进行了更改,这违背了在开发过程中使用Docker的目的。

容器为Alpine Linux,工作站Fedora 29和编辑器Atom

问题

还有另一种方法,这样我的工作站和容器都可以读取/写入相同的文件吗?

最佳答案

有多种方法可以执行此操作,但是主要问题是绑定(bind)安装不包含任何UID映射功能,主机上的UID是容器内显示的内容,反之亦然。如果这两个UID不匹配,则您将读写具有不同UID的文件,并且可能会遇到权限问题。

选项1:在VirtualBox中获取Mac或部署docker。这两个环境都具有文件系统集成,可以动态更新UID。对于Mac,这是通过OSXFS实现的。请注意,这种便利会带来性能损失。

选项2:更改主机。如果主机上的UID与容器内的UID相匹配,则不会遇到任何问题。您只需在主机上的用户上运行一个usermod来在那里更改您的UID,事情就会发生,至少要等到您在容器内运行具有不同UID的其他镜像时为止。

选项3:更改图片。有些人会将镜像修改为与环境匹配的静态UID,通常会与生产环境中的UID匹配。其他人将通过--build-arg UID=$(id -u)之类的构建arg作为build命令的一部分传递,然后通过Dockerfile传递诸如以下内容:

FROM alpine
ARG UID=1000
RUN adduser -u ${UID} app

不利的一面是每个开发人员可能需要不同的镜像,因此他们要么在每个工作站上本地构建,要么您集中构建多个镜像,一个针对开发人员中存在的每个UID。这些都不是理想的。

选项4:更改容器UID。这可以在撰写文件中完成,也可以在一个单独的容器中完成,例如 docker run -u $(id -u) your_image。现在,该容器将使用新的UID运行,并且可以访问该卷中的文件。但是,容器内的用户名不一定会映射到您的UID,这对于您在容器内运行的任何命令来说似乎都很奇怪。更重要的是,用户未在卷中隐藏的容器内用户拥有的任何文件都将具有原始UID,并且可能无法访问。

选项5:放弃,以root用户身份运行所有内容,或将权限更改为777,以允许所有人不受限制地访问目录。这不会映射到您应如何在生产环境中运行事物,并且容器仍可能会以有限的权限编写新文件,从而使您无法在容器外部访问它们。这还会带来安全风险,即以root用户身份运行代码或使文件系统保持打开状态,以便主机上任何用户均可读写。

选项6:设置一个动态更新您的容器的入口点。尽管不想更改您的图像,但这是我偏爱的完整性解决方案。您的容器确实需要以root用户身份启动,但只能在开发中启动,并且该应用程序仍将以用户身份运行,与生产环境匹配。但是,该入口点的第一步将是更改容器内用户的UID / GID,以使其与卷的UID / GID相匹配。这类似于选项4,但是镜像中未被卷替换的文件现在具有正确的UID,并且容器内的用户现在将显示更改后的UID,因此 ls之类的命令将显示容器内的用户名,而不是一个UID可能会映射到另一个用户或根本没有映射。尽管这是对镜像的更改,但是代码仅在开发中运行,并且仅作为为该开发人员设置容器的简要入口点,此后,容器中的过程将与生产环境中的过程相同。

为了实现这一点,我进行了以下更改。首先,Dockerfile现在包含一个修复程序脚本和我推送到集线器的基础镜像中的gosu(这是一个Java示例,但是更改可以移植到其他环境中):
FROM openjdk:jdk as build
# add this copy to include fix-perms and gosu or install them directly
COPY --from=sudobmitch/base:scratch / /
RUN apt-get update \
&& apt-get install -y maven \
&& useradd -m app
COPY code /code
RUN mvn build
# add an entrypoint to call fix-perms
COPY entrypoint.sh /usr/bin/
ENTRYPOINT ["/usr/bin/entrypoint.sh"]
CMD ["java", "-jar", "/code/app.jar"]
USER app

entrypoint.sh脚本调用fix-perms,然后调用exec和gosu从根目录降级到应用程序用户:
#!/bin/sh
if [ "$(id -u)" = "0" ]; then
# running on a developer laptop as root
fix-perms -r -u app -g app /code
exec gosu app "$@"
else
# running in production as a user
exec "$@"
fi

开发人员撰写文件将装入该卷并以root身份启动:
version: '3.7'
volumes:
m2:
services:
app:
build:
context: .
target: build
image: registry:5000/app/app:dev
command: "/bin/sh -c 'mvn build && java -jar /code/app.jar'"
user: "0:0"
volumes:
- m2:/home/app/.m2
- ./code:/code

此示例摘自我的演示文稿,位于: https://sudo-bmitch.github.io/presentations/dc2019/tips-and-tricks-of-the-captains.html#fix-perms

我的基本镜像存储库中提供了有关修补程序代码和其他示例的代码: https://github.com/sudo-bmitch/docker-base

关于javascript - 我如何让主机和容器使用Docker读取/写入相同的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56184987/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com