tianon / gosu

Simple Go-based setuid+setgid+setgroups+exec
Apache License 2.0
4.73k stars 321 forks source link

Question: Perform root step down in derived container after ENTRYPOINT cmd in base container has run? #81

Closed rorytorneymf closed 3 years ago

rorytorneymf commented 3 years ago

I have a base container that has an ENTRYPOINT that needs to run as root:

FROM docker.io/opensuse/leap:latest

# Add scripts to be executed during startup
COPY startup /startup
ADD https://example.com/install-ca-cert.sh /startup/startup.d/install-ca-cert-base.sh
RUN chmod +x /startup/* /startup/startup.d/*

# Add Tini
ENV TINI_VERSION v0.18.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--", "/startup/startup.sh"]

And a derived container that looks like this. Originally I tried using the USER directive to change the user:

FROM docker.io/my-base-container:latest
RUN useradd -r -U -u 1001 appuser
USER appuser

However, running the derived container fails, because appuser does not have permissions to execute the startup scripts:

[12:43:28.364Z #006.??? INFO  -            -   ] startup.sh: Running startup scripts...
[12:43:28.367Z #006.??? INFO  -            -   ] startup.sh: Running install-ca-cert-base.sh...
[12:43:28.373Z #00D.??? INFO  -            -   ] install-ca-cert-base.sh: /bin/bash: /startup/startup.d/install-ca-cert-base.sh: Permission denied
[12:43:28.374Z #006.??? INFO  -            -   ] startup.sh: Error running install-ca-cert-base.sh

So, the ENTRYPOINT in the base container needs to run as root, but after ENTRYPOINT has run on the base container, I'd like to step down in the derived container as a non-root user. I'm trying to figure out how to do that using gosu?

I updated the base container to install gosu (using https://hub.docker.com/r/miktex/miktex-test-opensuse/dockerfile as an example as I'm using opensuse):

RUN    gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64" \
    && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64.asc" \
    && gpg --verify /usr/local/bin/gosu.asc \
    && rm /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu

I'm just trying to figure out how what I need to do in the derived container to perform the root user step down and switch to the appuser?

Many thanks.

rorytorneymf commented 3 years ago

This seems to work:

I tried creating a new entrypoint script, that would call the original entrypoint script, then switch the user:

#!/bin/bash

set -e

# Call original entrypoint
/tini -s /startup/startup.sh

# Add new (non-root) user
useradd --shell /bin/bash --system --user-group --create-home appuser

# Run supplied command as non-root user
exec /usr/local/bin/gosu appuser "$@"

Then in my derived Dockerfile just calling this new script:

ADD ./gosu-entrypoint.sh /usr/local/bin/gosu-entrypoint.sh
RUN chmod +x /usr/local/bin/gosu-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/gosu-entrypoint.sh"]