linux命令docker-v是空的

linux命令docker-v是空的,第1张

没有特权用户的情况下运行。使用了一些基于Linux的虚拟机,因此Docker命令可以在这些系统中没有特权用户的情况下运行,linux命令是对Linux系统进行管理的命令。对于Linux系统来丛则说,无论是中央处理器、内存、尺橘磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令渗困棚是它正常运行的核心,与之前的DOS命令类似。

Docker 提供了数据卷 绑定挂载 的机制简斗拦(volume bind mounts)来将主机上的文件 (file) 或者目录 (directory) 挂载进容器 (container)。也就是 docker run 命令中熟知的 -v 参数。根据 Docker 官方文档,绑定挂载一般适合于 三种场景 :

但是实际使用时,会遇到文件权限问题:

譬如执行如下命令创建一个容器,挂载当前目录到容器内,并在容器内向主机当前目录创建 tmp.txt:

主机当前目录出现了容器内创建的 tmp.txt,但是其权限、用户和组均是 root,其他用户不可写。

常见解决方法是可以通过 Docker 提供的 User 命令、 --user 参拦胡数 来指定容器内部的用户和组的 id,譬如:

可以看到输出,current_user 处会显示主机当前用户的名字,所以解决了主机用户对挂载的卷没有权限的问题。

user 参数的缺陷

使用 user 参数有一些缺陷,如果你进入容器内部的 terminal,会显示如下内容:

b.sh 的用户名会显示 I have no name!,这是因为我们通过 --user 参数指定了容器内部的用户 id,但该 id 不存在于容器内的 /etc/passwd 文件中。

除此之外,使用 user 参数仍然存在权限问题:

除了绑定挂载的主机路径之外的所有路径,对于容器内部的用户都没有写权限。

这也是不可接受的,因为容器运行过程中我们可能会进行一些临时文件的写入,这些临时文件我们并不想要写到主机的挂载目录,但除了挂载路径之外的任何路径容器都没有写入权限。

譬如我们在主机上创建 models 目录。

我们使用 Docker 挂载 models 目录,然而在 Docker 容器内部除了 models 文件夹都没有访问权限。

这可以通过增加挂载路径:

这样容器运行过程往 /project 写的临时文件都会出现在主机上。

可见, user 参数并不能解决所有问题。它存在两个问题:

我们需要一种手段,既可以像 user 参数一样在容器运行时可以将用户切换到和主机相同的用户,又希望 Docker 容器保留 root 用户,并给主机用户想要访问的目录授权(对特定目录 chown 、 chmod 等)。

Docker 官方文档对 Entrypoint 介绍时给出了 一种最佳实践 。

编写如下的 Dockerfile:

该 Dockerfile 中安装了一个 gosu 的工具,并设置了程序的 Entrypoint。由于 Docker 内使用 sudo 可能导致一些不可预知的 TTY 和信号转发问题,所以 Docker 官方推荐了使用 gosu 这个工具,用于保持容器在 root 用户下运行,并用 sudo 来切换到指定用户。

其中 docker-entrypoint.sh 内容如下:

可以看到 docker-entrypoint.sh 中创建了一个名为 user 的用户,该用户的 uid 由 docker run 的参数传入,这里利用了 linux 系统的一个特点,容器内外用户权限的记录和用户的名字无关,只和 uid 有关,因此容器内我们将用户命名为 user 没有影响。docker-entrypoint.sh 最后一行调用 gosu 来切换到 user 用户并执行 Dockerfile 中的用户命令。

有了如上两个脚本,我们构建镜像并执行:

运行容器时指定 LOCAL_USER_ID 参数:

可见不仅容器内往挂载目录 /project/models 写入的文件 model.txt 所有者是主机用户,而且在容器内往非挂载目录 /project/tmp.txt 写入销简文件也不会遇到权限问题。

Docker 运行时容器内默认使用 root 用户运行,但是我们不是总是想要用 root 用户,因为有时候我们希望容器计算产生一些文件,并通过 volume 的绑定挂载在主机上获取。特别是我们用 jenkins 等工具写一些持续集成的脚本时候。容器内用 root 用户运行会导致产生的文件也是 root 用户的,主机上没有读取权限。因此我们需要让容器在运行的时候切换到主机上的用户。

Docker 对于这种情况仍然没有提供足够便利的基础设施,我们采用了 Docker 官方目前推荐的一个方式,通过编写一个 docker-entrypoint.sh 脚本作为 Dockerfile 的 Entrypoint,脚本中创建和主机上相同 uid 的用户,并通过 gosu 工具切换到该用户执行命令。 uid 需要在 docker run 阶段通过参数传入。我们在脚本中设置了缺省 uid ,上面的脚本随机选择了一个 9001,注意要将该缺省值避免设置成和 Docker 镜像中存在的用户冲突的 uid。

参考链接:

1. 拉取镜像,部署应用

    docker pull + 镜像地址

    docker run --name 应用名称 -d -p 对外端口:容器内端口  镜像名称:版本号

    (如果容器内的配置文件本身存在问题就会导致该容器无法运行,docker ps查看正在运行的容器,docker ps -a 查看所猛肆有容器,docker logs 容器id 可以查看容器日志)

2. 将容器内的配置文件拷贝到本机上修改(如果在容器内修橘雹改,重启后就会失效)

    docker cp 容器id:容器中文件的路径 本机目的路径

3.  将本机修改后的文件传入容器内替换

    docker cp 本机文件路径 容器id:容器内文件路径

4. 重启容器

    docker restart 容器id

1. 进入容器

docker exec 容器ID

其他常见命令见:https://www.jianshu.com/writer#/notebooks/49874836/notes/86218928

1. 如果访问仍然存在问题,首先检查容器内端口是否正确

2. 将上述第三步换成以下步骤,将本机的文件挂载到容器内,而非替换文件(如Nginx的地址修改,重启后会回到原来镜像拉取的地址)

    1. 移除原来的容器 

        rm -f 容器id

    2. 重新运行容器并将写好的配置文件挂载到容器内

        docker run --name 容器名称 -d -p 对外端口:容器内端口 -v 本机配圆知帆置文件路径:容器内配置文件路径:ro 镜像地址:版本号


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8179711.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-14
下一篇 2023-04-14

发表评论

登录后才能评论

评论列表(0条)

保存