1

I have a simple Dockerfile

FROM python:3.10-alpine

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Set arguments
ARG USERNAME=jpg
ARG USER_DIR=/home/$USERNAME
ARG WORK_DIR=$USER_DIR/app

# Creating a non-root user
RUN adduser -S $USERNAME

# Switching the user
USER $USERNAME

# Create a new directory to keep the project files
RUN mkdir $WORK_DIR

# Copy local contents into container
COPY ./ $WORK_DIR

# Setting newly created directory as PWD
WORKDIR $WORK_DIR

# Adding user's bin path to `PATH` variable
ENV PATH "$PATH:$USER_DIR/.local/bin"

# Installing pip packages
RUN pip install pip -U

I built the image using following command

docker build . -t test-img:latest

After the successfull image build, run the image using

docker run -i -t test-img:latest python

This gave me an interactive shell, as expected. Also, I tried to pull the user info using getuser(...) function as well

Python 3.10.10 (main, Mar 14 2023, 03:01:12) [GCC 12.2.1 20220924] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import getpass
>>> getpass.getuser()
'jpg'
>>> 

Then, I moved to another terminal and logged in to the same container as root user. After logged-in, tried to switch the user to jpg (which is defined within the Dockerfile)

$ docker exec -it -u root f6dc515bca29 sh                                                                                                                                                          
/home/jpg/app # su - jpg
This account is not available
/home/jpg/app # su - "jpg"
This account is not available
/home/jpg/app # su -l "jpg"
This account is not available
/home/jpg/app # su -l jpg
This account is not available
/home/jpg/app # 

Question

How can I switch the user to jpg (or any non-root user) in an alpine-based container from root?

Note: It is mandatory to log in as root (-u root) in an exec session because this is to simulate a situation of AWS Fargate containers.

JPG
  • 82,442
  • 19
  • 127
  • 206
  • 1
    I can easily repro in a base `alpine` container. If I remove the `-S` option to `adduser` the account is available. Do you have a particular reason to want to create a system user? Do you actually need to run an interactive shell as this user? – tripleee Mar 29 '23 at 18:04
  • 1
    Start a new `docker exec` shell with the `-u username` you need. Don't bother trying to use `su` or `sudo` in a debugging shell like this. Also remember that anything you do in this shell will be lost as soon as the container exits; I wouldn't invest a lot of time in `exec`-based workflows. – David Maze Mar 29 '23 at 18:57
  • 1
    (The username and filesystem paths are local to the image, and I wouldn't bother passing them as `ARG`s. If you run `WORKDIR` first, it will create the directory, and you can `COPY files ./` without repeating the path. Don't forget to set a `CMD` that actually runs your program.) – David Maze Mar 29 '23 at 18:59
  • @DavidMaze Thanks for your input. But, It is mandatory to log in as root (`-u root`) in an `exec` session because this is to simulate a situation of AWS Fargate containers. – JPG Mar 30 '23 at 02:45
  • @tripleee You're right. Removing the `-S` flag fixed the issue. Do you know what could go wrong with the `-S` flag? If you write that as an answer, I'd more happy to accept it :) – JPG Mar 30 '23 at 02:57

1 Answers1

2

You're getting the This account is not available message because running adduser -S explicitly sets the shell for the account to /sbin/nologin (because you've asked for a system account with -S, the assumption is you don't expect interactive logins for this user).

You can explicitly set the shell for the named user:

/ # adduser -S -s /bin/sh jpg
/ # su - jpg
710ed667ddb2:~$ whoami
jpg

...or, as @tripleee suggests, just drop the -S from your adduser invocation and create a normal user; in this case, the shell will default to /bin/sh.

larsks
  • 277,717
  • 41
  • 399
  • 399