在码头工人,货柜内创建的文件往往有不可预知的所有权,同时从主机检查它们。 一个卷上的文件的所有者是根默认(UID 0),但只要非根用户帐户都参与了容器和写入文件系统,拥有者成为从主机的角度或多或少随机的。
这是一个问题,当你需要使用它调用泊坞窗命令相同的用户帐户的主机访问量数据。
典型的变通办法
- 迫使用户的UID在创建时在Dockerfiles(非便携式)
- 使所述主机用户的UID到
docker run
命令作为环境变量,然后运行一些chown
在一个入口点脚本的卷上的命令。
这两种解决方案可以给在容器外面的实际权限一些控制。
我期望的用户命名空间为最终解决这个问题。 我已经运行一些测试与最近发布的版本1.10和--userns重新映射设置为我的桌面帐户。 但是,我不知道它可以使文件的所有权上安装的卷容易对付,恐怕它实际上是相反的。
假设我开始这个基本的容器
docker run -ti -v /data debian:jessie /bin/bash
echo 'hello' > /data/test.txt
exit
然后检查来自主机的内容:
ls -lh /var/lib/docker/100000.100000/volumes/<some-id>/_data/
-rw-r--r-- 1 100000 100000 6 Feb 8 19:43 test.txt
这个数字“100000”是我的主机用户的子UID,但因为它不符合我的用户的UID,我还是不能没有特权编辑的test.txt。 该子用户似乎并不与泊坞窗的外面我的实际经常用户的任何亲和力。 这不是映射回。
早在这个帖子里面包括主机和容器之间对准的UID提到的解决方法不要再因工作UID->sub-UID
发生在命名空间映射。
那么,有没有一种方式来运行启用了(为了提高安全性)用户的命名空间泊坞窗,同时还使其能够运行搬运工人把自己卷上生成的文件主机用户?
如果你能提前酝酿的用户和组,那么它可能使主机用户对应于集装箱内命名空间的用户分配UID和GID在这种特定的方式。
下面是一个例子(Ubuntu的14.04,多克尔1.10):
创建一些用户有固定的数字ID:
useradd -u 5000 ns1 groupadd -g 500000 ns1-root groupadd -g 501000 ns1-user1 useradd -u 500000 -g ns1-root ns1-root useradd -u 501000 -g ns1-user1 ns1-user1 -m
手动编辑自动生成的ID下级范围/etc/subuid
和/etc/subgid
文件:
ns1:500000:65536
(注意没有记录ns1-root
和ns1-user1
由于MAX_UID
和MAX_GID
在限制/etc/login.defs
)
启用用户命名空间中/etc/default/docker
:
DOCKER_OPTS="--userns-remap=ns1"
重新启动后台程序service docker restart
,确保/var/lib/docker/500000.500000
创建目录。
现在,容器里面你有root
和user1
,并在主机上- ns1-root
和ns1-user1
,与之相配的ID
UPDATE:保证非root用户有固定的容器中的ID(如USER1 1000:1000),图像生成过程中明确创建它们。
试驾:
准备卷目录
mkdir /vol1 chown ns1-root:ns1-root /vol1
从容器试试吧
docker run --rm -ti -v /vol1:/vol1 busybox sh echo "Hello from container" > /vol1/file exit
从主机尝试
passwd ns1-root login ns1-root cat /vol1/file echo "can write" >> /vol1/file
不可移植的,看起来像一个黑客,但工程。
您可以通过使用避免权限问题docker cp
命令 。
所有权被设置为用户和主要组的目的地。 例如,复制到一个容器文件与创建UID:GID
根用户。 复制到本地机文件与创建UID:GID
其调用用户的docker cp
命令。
这里就是你们的榜样切换到使用docker cp
:
$ docker run -ti -v /data debian:jessie /bin/bash
root@e33bb735a70f:/# echo 'hello' > /data/test.txt
root@e33bb735a70f:/# exit
exit
$ docker volume ls
DRIVER VOLUME NAME
local f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93
$ sudo ls -l /var/lib/docker/100000.100000/volumes/f073d0e001fb8a95ad8d919a5680e72b21a457f62a40d671b63c62ae0827bf93/_data
total 4
-rw-r--r-- 1 100000 100000 6 Oct 6 10:34 test.txt
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e33bb735a70f debian:jessie "/bin/bash" About a minute ago Exited (0) About a minute ago determined_hypatia
$ docker cp determined_hypatia:/data/test.txt .
$ ls -l test.txt
-rw-r--r-- 1 don don 6 Oct 6 10:34 test.txt
$ cat test.txt
hello
$
不过,如果你只想读出一个容器的文件,你不需要指定的音量。 此示例使用一个名为容器,而不是一个名为量:
$ docker run -ti --name sandbox1 debian:jessie /bin/bash
root@93d098233cf3:/# echo 'howdy' > /tmp/test.txt
root@93d098233cf3:/# exit
exit
$ docker cp sandbox1:/tmp/test.txt .
$ ls -l test.txt
-rw-r--r-- 1 don don 6 Oct 6 10:52 test.txt
$ cat test.txt
howdy
$
我发现一个名为卷有用的,当我想将文件复制到一个容器中,如描述的这个问题 。
一个解决办法是动态分配的编译时间用户的UID相匹配的主机。
例如Dockerfile
:
FROM ubuntu
# Defines argument which can be passed during build time.
ARG UID=1000
# Create a user with given UID.
RUN useradd -d /home/ubuntu -ms /bin/bash -g root -G sudo -u $UID ubuntu
# Switch to ubuntu user by default.
USER ubuntu
# Check the current uid of the user.
RUN id
# ...
然后建立如下:
docker build --build-arg UID=$UID -t mycontainer .
并且运行:
docker run mycontainer
如果你现有的容器,创建具有以下的包装容器Dockerfile
:
FROM someexistingcontainer
ARG UID=1000
USER root
# This assumes you've the existing user ubuntu.
RUN usermod -u $UID ubuntu
USER ubuntu
这可以被包裹在docker-compose.yml
喜欢:
version: '3.4'
services:
myservice:
command: id
image: myservice
build:
context: .
volumes:
- /data:/data:rw
然后建立和运行:
docker-compose build --build-arg UID=$UID myservice; docker-compose run myservice
文章来源: Docker and --userns-remap, how to manage volume permissions to share data between host and container?