使用Docker和--privileged构建

19

我正在使用这个指南来使用Amazon Lex和Raspberry Pi构建语音套件,但我需要使用Docker。

问题在于,指南curl并运行的脚本需要访问/dev/tty。当运行Docker容器时,我可以授予对/dev/tty的访问权限,但是我不知道如何在构建容器时执行此操作。

我的Dockerfile如下:

FROM resin/rpi-raspbian

WORKDIR /app

ADD . /app

#The script requires these
RUN apt-get update
RUN apt-get install iputils-ping

#The script has to be run with sudo priviliges but not as root
USER root
ADD /sudoers.txt /etc/sudoers
RUN chmod 440 /etc/sudoers


RUN useradd -ms /bin/bash lex
RUN echo 'lex:test' | chpasswd

RUN curl https://get.pimoroni.com/phatdac | bash 

USER lex

EXPOSE 80

#Comment the last RUN command and uncomment this
#CMD curl https://get.pimoroni.com/phatdac | bash 

当我尝试构建容器时,使用以下命令:

docker build -t raspi1 .

因为无法访问 /dev/tty,所以脚本会崩溃。

运行容器时,可以使用此脚本授予对 /dev/tty 和 /dev/snd 的访问权限。

#!/bin/sh

 docker run -ti --rm \
     -v /dev/snd:/dev/snd \
      --privileged \
     raspi7 

然后尝试在Dockerfile中使用CMD启动脚本。但是如果这样做,每次运行时都需要使用脚本,并且还需要在脚本完成后对其他内容进行RUN操作,这在构建Dockerfile时很好。

TLDR; 如何在构建docker镜像时授予/dev/tty和/dev/snd的权限?


无关紧要,但是你应该将你的RUN命令分组(参见https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/),而且你的`user ROOT命令是无用的,因为默认情况下你就是root用户,除非你使用了USER xxx`命令。 - user2915097
请参考以下链接:https://dev59.com/eZzha4cB1Zd3GeqPCD-f#40442502 - user2915097
谢谢,但这些还不能解决这个问题。 - Alqio
3个回答

8
当前 Docker 不支持暴露设备,或者说在构建时进行特权操作。

根据 @cpuguy83 的说法,你现在正在做的——在没有访问主机的情况下构建可移植镜像,并在容器首次启动时完成配置——是正确的做法:

在第一次容器启动时完成这种操作正是正确的方式。 这是一个运行时配置,不应该在镜像中。

请参阅 bountysource
还有一个旧的但仍然开放的moby的问题。

6

moby的问题已被@Greg提出并解决。

现在可以使用docker buildx构建具有特权权限的镜像:

  1. In Dockerfile (ref),
    1. set the Dockerfile version in the beginning of file:
      # syntax=docker/dockerfile:1.3-labs
      
    2. add the --security=insecure option to the RUN commands that require privileged operations:
      RUN somecommand
      
      becomes
      RUN --security=insecure somecommand
      
  2. create and use a docker-container driver to build the image (ref):
    docker buildx create --driver-opt image=moby/buildkit:master  \
                         --use --name insecure-builder \
                         --buildkitd-flags '--allow-insecure-entitlement security.insecure'
    docker buildx use insecure-builder
    docker buildx build --allow security.insecure ...(other build args)...
    docker buildx rm insecure-builder
    
然而,需要注意的是这种方法目前存在一些限制。 docker-container driver无法访问docker imageref),因此所有由FROM引用的映像都需要在映像注册表中。并且为了使构建后的映像对docker image可见,您可能需要在docker buildx build命令中添加output选项。

1
您的问题可能是由于在您的 Docker 镜像中不存在 /dev/snd。当您运行容器时,实际上是将主机操作系统的 /dev/snd 挂载到容器内,以便可以运行脚本。请查看以下内容:
[INSERT] > cat Dockerfile
FROM resin/rpi-raspbian

RUN ls /dev && ls /dev/tty && ls /dev/snd


[INSERT] > docker build .
Sending build context to Docker daemon  39.94kB
Step 1/2 : FROM resin/rpi-raspbian
 ---> d008ca006edc
Step 2/2 : RUN ls /dev && ls /dev/tty && ls /dev/snd
 ---> Running in 0b738007c71c
core
fd
full
mqueue
null
ptmx
pts
random
shm
stderr
stdin
stdout
tty
urandom
zero
/dev/tty
/bin/ls: cannot access /dev/snd: No such file or directory
The command '/bin/sh -c ls /dev && ls /dev/tty && ls /dev/snd' returned a non-zero code: 2

正如您所见,/dev/tty 存在,您可以访问它。/dev/snd 不存在,并且您不在运行的容器内,因此无法将其作为卷挂载(在运行容器时进行了这样的操作)。我建议尝试更全面地了解您正在运行的脚本正在执行的操作,评估它是否需要访问主机的 /dev/snd,如果需要,则只能在运行的容器内运行脚本,因为镜像没有主机机器的概念。

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