Use sudo inside Dockerfile (Alpine)
Asked Answered
O

2

36

I have this Dockerfile ...

FROM keymetrics/pm2:latest-alpine

RUN apk update && \
    apk upgrade && \
    apk add \
       bash

COPY . ./

EXPOSE 1886 80 443

CMD pm2-docker start --auto-exit --env ${NODE_ENV} ecosystem.config.js

How can I execute the CMD command using sudo ?

I need to do this because the port 443 is allowed only for sudo user.

Oruro answered 11/3, 2018 at 22:51 Comment(11)
You are still root when CMD is executed. What makes you think that's not the case? Can you share the command line you used to start your container.Pleven
Docker itself runs as root and a container will default to root unless you have a USER set in the image, which aren't in the base image or your Dockerfile. Can you explain a bit more about what you're trying to do and what is going wrong? Is there an error message?Infestation
@ChristopheSchmitz I know that the CMD command is executed, my question is how to execute him with sudoOruro
@Infestation I need to execute pm2 command with sudo privileges because I need to run it with port 443. Locally in my machine I can run pm2 with command sudo pm2 sart but to deploy my app I'm using docker and I need to run the pm2 command with sudo tooOruro
You are already root when CMD is executed. sudo won t help there.Pleven
@ChristopheSchmitz this command throw error error: listen eacces 0.0.0.0:443 the reason is to run node app using ports bellow 1024 I need to execute it with sudoOruro
@Oruro That shouldn't be happening in the container. Can you add your docker run command as well? Is that error appearing in the docker logs/output?Infestation
This is happening because listening on ports below 1024 requires node to be started using sudo. This is explained here: #35069212 However, I also would like to be able to set up a docker image that allows node to listen on port 80 without requiring a proxy server, just for testing purposes. It would be great to find out how to do this. In my Dockerfile I use CMD ["npm", "start"] which causes an error if the port is set to 80. I tried CMD ["sudo", "npm", "start"] but that fails - sudo not foundRadiobroadcast
@ChristopheSchmitz it's not a question of which user is in place but rather a question of wanting to be able to execute "sudo npm start" so as to avoid the limitation on ports below 1024.Radiobroadcast
Can you share your docker run command, as ask by other?Pleven
was a solution found?Meneses
S
54

The su-exec can be used in alpine. Do add it the package, if not already available, add the following to your Dockerfile

RUN apk add --no-cache su-exec

Inside your scripts you'd run inside docker you can use the following to become another user:

exec su-exec <my-user> <my command>

Alternatively, you could add the more familiair sudo package while building your docker-file Add the following to your Dockerfile that's FROM alpine

RUN set -ex && apk --no-cache add sudo

After that you can use sudo

sudo -u <my-user> <my command>
Septillion answered 21/3, 2019 at 10:1 Comment(1)
su-exec wasn't available in my alpine container. I had to modify its Dockerfile to include: RUN apk add --no-cache su-exec. sudo didn't help me as it was asking for the user's password which I didn't know.Fayalite
K
39

Sudo isn't shipped with Alpine images normally, and it rarely makes sense to include it inside of any container. What you need isn't sudo to bind to a low numbered port, but the root user itself, and sudo is just a common way to get root access in multi-user environments. If a container included sudo, you would need to either setup the user with a password, or allow commands to run without a password. Regardless of which you chose, you now have a privilege escalation inside the container, defeating the purpose of running the container as a normal user, so you may as well run the container as root at that point.

If the upstream image is configured to run as a non-root user (unlikely since you run apk commands during the build), you can specify USER root in your Dockerfile, and all following steps will run as root by default, including the container entrypoint/cmd.

If you start your container as a different user, e.g. docker run -u 1000 your_image, then to run your command as root, you'd remove the -u 1000 option. This may be an issue if you run your container in higher security environments that restrict containers to run as non-root users.

If your application itself is dropping the root privileges, then including sudo is unlikely not help, unless the application itself has calls to sudo internally. If that's the case, update the application to drop root privileges after binding to the ports.

Most importantly, if the only reason for root inside your container is to bind to low numbered ports, then configure your application inside the container to bind to a high numbered port, e.g. 8080 and 8443. You can map this container port to any port on the host, including 80 and 443, so the outside world does not see any impact. E.g. docker run -p 80:8080 -p 443:8443 your_image. This simplifies your image (removing tools like sudo) and increases your security at the same time.

Kinship answered 14/5, 2019 at 15:4 Comment(2)
thank you ! sometimes what we are looking for is not what we actually need. This was the case for me and your explanation helped me a lot !Penn
Fantastic answer, I was not aware that higher number ports didn't require root privileges.Faunus

© 2022 - 2024 — McMap. All rights reserved.