Skip to content

Commit

Permalink
Merge pull request #177 from leolivier:run-as-non-root-in-container
Browse files Browse the repository at this point in the history
Run-as-non-root-in-container issue #147
  • Loading branch information
leolivier authored Dec 21, 2024
2 parents aa40352 + a9d0913 commit fef9645
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 50 deletions.
41 changes: 24 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
FROM python:3.12-slim

ARG USER=cm_user
ARG UID=5678
ARG APP_DIR=/app

LABEL org.opencontainers.image.source=https://github.com/leolivier/cousins-matter
LABEL org.opencontainers.image.description='Docker image for the Cousins Matter application (https://github.com/leolivier/cousins-matter)'
LABEL org.opencontainers.image.url=https://github.com/leolivier/cousins-matter
LABEL org.opencontainers.image.branch=main
LABEL org.opencontainers.image.licenses=MIT


EXPOSE 8000

# Keeps Python from generating .pyc files in the container
Expand All @@ -15,33 +18,37 @@ ENV PYTHONDONTWRITEBYTECODE=1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED=1

WORKDIR /app
WORKDIR ${APP_DIR}

# install lighttpd for serving static and media files, redis for chat, sqlite3 and acl for init
# install lighttpd for serving static and media files, redis for chat, sqlite3 for installing database
# We must update twice as we need first to install gpg before installing redis
RUN apt-get update &&\
apt-get install -y lighttpd lsb-release curl gpg sqlite3 acl &&\
apt-get install -y lighttpd lsb-release curl gpg sqlite3 sudo supervisor && \
curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg &&\
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" > /etc/apt/sources.list.d/redis.list &&\
apt-get update &&\
apt-get install -y redis &&\
mkdir -p "/var/log/supervisord" "/var/run/supervisord" &&\
rm -rf /var/lib/apt/lists/*

# Allows docker to cache installed dependencies between builds
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Creates a non-root user with an explicit UID and adds permission to access the /app folder
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
# RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
# USER appuser

COPY . .

# runs the production server
ENTRYPOINT ["/app/scripts/entrypoint.sh"]
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
CMD ["supervisord", "-c", "/app/supervisord.conf"]

VOLUME [ "/app/data" ]
VOLUME [ "/app/media" ]
# This is the user that will run the application but through supervisord so
# we keep running as root for supervisord which will run things as $USER
RUN adduser --uid ${UID} --disabled-password --gecos "" ${USER} && \
chown -R ${USER}:${USER} ${APP_DIR}

# now copy all (but .dockerignore rules) with $USER as proprietary
COPY --chown=${USER}:${USER} . .

ENV USER=${USER}
ENV APP_DIR=${APP_DIR}
# runs the production server (as root)
ENTRYPOINT ["./scripts/entrypoint.sh"]
# supervisord must run as root
CMD ["supervisord", "-c", "./supervisord.conf"]

VOLUME ./data ./media
30 changes: 15 additions & 15 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
django>=5.1.4
pillow>=10.4.0
django-crispy-forms>=2.3
crispy-bulma>=0.11.0
django-environ>=0.11.2
django-email-validation>=2.0.5
django-simple-captcha>=0.6.0
daphne>=4.1.2
supervisor>=4.2.5
reportlab>=4.2.2
channels>=4.1.0
channels_redis>=4.2.0
Babel>=2.15
django-cors-headers>=4.4.0
packaging>=24.0
django~=5.1.4
pillow~=11.0.0
django-crispy-forms~=2.3
crispy-bulma~=0.11.0
django-environ~=0.11.2
django-email-validation~=2.0.5
django-simple-captcha~=0.6.0
daphne~=4.1.2
supervisor~=4.2.5
reportlab~=4.2.5
channels~=4.2.0
channels_redis~=4.2.0
babel~=2.16.0
django-cors-headers~=4.6.0
packaging~=24.2
3 changes: 0 additions & 3 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#!/bin/bash
export APP_DIR=/app
. ./scripts/prepare-envt.sh || exit 1
# add full access to /app to www-data for redis and ligthttpd
setfacl -m u:www-data:rwx /app
echo "starting $@" # as provided in the Dockerfile
exec "$@"
16 changes: 7 additions & 9 deletions scripts/prepare-envt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ then echo "Must be run from the cousins-matter directory!"
fi

for file in lighttpd.conf supervisord.conf
do cat template.$file | sed -e "s,{%APP_DIR%},$APP_DIR,g" > $file
do cat template.$file | sed -e "s,{%APP_DIR%},$APP_DIR,g;s,{%USER%},$USER,g" > $file
done

echo "collecting statics..."
python manage.py collectstatic --no-input
sudo -u $USER python manage.py collectstatic --no-input
echo "migrating the database..."
python manage.py migrate
python manage.py check
sudo -u $USER python manage.py migrate
sudo -u $USER python manage.py check

echo "importing predefined pages"
./scripts/import-flatpages.sh
echo "import done..."

sudo=''
if [[ -n "$EUID" && $EUID -ne 0 ]];
then sudo='sudo'
fi
$sudo mkdir -p "/var/log/supervisord" "/var/run/supervisord"
echo "environment is ready..."
5 changes: 3 additions & 2 deletions template.lighttpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ $HTTP["url"] =~ "^/static/" {
} else $HTTP["url"] =~ "^/chat" { # websocket for the chat, add upgrade header
proxy.server = ("/" =>
( "cousinsmatter socket" => (
"socket" => "/var/run/cousinsmatter.socket"
# sockets are created in APP_DIR for running as non root
"socket" => "{%APP_DIR%}/cousinsmatter.socket"
))
)
proxy.header = ( "upgrade" => "enable" )
} else $HTTP["url"] =~ "" {
proxy.server = ("/" =>
( "cousinsmatter socket" => (
"socket" => "/var/run/cousinsmatter.socket"
"socket" => "{%APP_DIR%}/cousinsmatter.socket"
))
)
}
8 changes: 4 additions & 4 deletions template.supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ stderr_logfile_maxbytes=0
directory={%APP_DIR%}
autostart=true
autorestart=true
command=daphne -u /var/run/cousinsmatter.socket --proxy-headers cousinsmatter.asgi:application
user=root
command=daphne -u {%APP_DIR%}/cousinsmatter.socket --proxy-headers cousinsmatter.asgi:application
user={%USER%}

[program:lighttpd]
stdout_logfile=/dev/stdout
Expand All @@ -28,7 +28,7 @@ directory={%APP_DIR%}
autostart=true
autorestart=true
command=lighttpd -D -f {%APP_DIR%}/lighttpd.conf
user=www-data
user={%USER%}

[program:redis]
stdout_logfile=/dev/stdout
Expand All @@ -39,4 +39,4 @@ directory={%APP_DIR%}
autostart=true
autorestart=true
command=redis-server
user=www-data
user={%USER%}

0 comments on commit fef9645

Please sign in to comment.