Build with docker and --privileged
Asked Answered
D

3

20

I'm using this guide to Build a Voice Kit with Amazon Lex and a Raspberry Pi, but I need to use Docker. The problem is that the script that the guide curls and runs requires access to /dev/tty. I can grant access to /dev/tty when running docker containers, but I don't know how to do that when building containers.

My Dockerfile looks like this:

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 

And when I try to build the container with

docker build -t raspi1 .

it crashes on the script, because it can't access /dev/tty.

When running a container, I can use this script to grant access to /dev/tty and /dev/snd

#!/bin/sh

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

and then try to use the script on the startup with CMD in the Dockerfile. But if I do that, then I need to use the script every time when running and I also need to do RUN on other stuff after the script has finished which would be nice to have on the Dockerfile when building.

TLDR; How to grant privileges to /dev/tty and /dev/snd when building a docker image?

Dictator answered 4/1, 2018 at 15:41 Comment(3)
unrelated, but you should group your RUN (see docs.docker.com/engine/userguide/eng-image/…) , and your line user ROOT is useless, as by default your are root, unless you do USER xxxwhat you do laterSmart
see also #40442784Smart
Thanks, but those don't solve this problem yet.Dictator
F
9

The moby's issue mentioned by @Greg has been closed.

It is now possible to build images with privileged rights with 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
    

However, note that this method has some restrictions so far. A docker-container driver has no access to docker image (ref), so all the images referenced by FROM need to be in a image registry. And for the built image to be visible to docker image, you may need to add the output option in the docker buildx build command.

Fiberboard answered 23/5, 2022 at 2:52 Comment(2)
Thank you for that tidbit ... I'm trying to build linux-from-scratch in a docker container, and I needed a chroot complete with /dev, /proc, /sys, and /dev/pts .... to complete the build process. And it forced me to do in a docker run what should be done in a docker build, if for no other reason I so I don't have to rebuild 30 packages because teh 31st one failed to compile. I've been seriously conisdering learning go and hacking buildx, just to be able to say for i in proc sys dev dev/pts; do mkdir -p /$i ; mount --bind /$i /lfs/$i; done. I'm so happy I could plottz.Hadik
adding container in the list of containers, you need the --load option -docker buildx build --load --allow security.insecure -t my_container docs.docker.com/build/drivers/docker-container/…Antalya
A
8

Docker currently doesn't support exposing devices, or for that matter privileged operations when building.

According to @cpuguy83 what you are doing now - building a portable image without access to the host and completing the configuration when the container is first started - is the right thing to do:

Doing this kind of stuff at first container start is exactly the right way to go. It's a runtime configuration it shouldn't be in the image.

See bountysource.

There is also and old but still open moby's issue.

Adverb answered 17/7, 2019 at 14:3 Comment(0)
A
1

Your problem is probably that /dev/snd doesn't exist inside your docker image. When you run your container, you are actually mounting your host OS /dev/snd inside the container so that your script can be run. Take a look at the following:

[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

As you can see, /dev/tty exists, and you have access to it. /dev/snd does not exist, and you aren't inside a running container so you can't mount it as a volume (which you are doing when running the container). I would recommend trying to more fully understand what the script you are running is doing, assess whether it needs access to the host machine's /dev/snd, and if so you may only run the script inside the running container as an image doesn't have any concept of a host machine.

Aquanaut answered 4/1, 2018 at 18:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.