Skip to content

Commit 612ecff

Browse files
feat: Support running Docker container as non-root (#599)
1 parent 33c7328 commit 612ecff

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

Dockerfile

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,22 @@ ENV SOURCEBOT_LOG_LEVEL=info
182182
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
183183
# ENV SOURCEBOT_TELEMETRY_DISABLED=1
184184

185+
# Configure dependencies
186+
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor uuidgen curl perl jq redis postgresql postgresql-contrib openssl util-linux unzip
187+
188+
ARG UID=1500
189+
ARG GID=1500
190+
191+
# Always create the non-root user to support runtime user switching
192+
# The container can be run as root (default) or as sourcebot user using docker run --user
193+
RUN addgroup -g $GID sourcebot && \
194+
adduser -D -u $UID -h /app -S sourcebot && \
195+
adduser sourcebot postgres && \
196+
adduser sourcebot redis && \
197+
adduser sourcebot node && \
198+
mkdir /var/log/sourcebot && \
199+
chown sourcebot /var/log/sourcebot
200+
185201
COPY package.json yarn.lock* .yarnrc.yml public.pem ./
186202
COPY .yarn ./.yarn
187203

@@ -214,9 +230,6 @@ COPY --from=shared-libs-builder /app/packages/db ./packages/db
214230
COPY --from=shared-libs-builder /app/packages/schemas ./packages/schemas
215231
COPY --from=shared-libs-builder /app/packages/shared ./packages/shared
216232

217-
# Configure dependencies
218-
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor uuidgen curl perl jq redis postgresql postgresql-contrib openssl util-linux unzip
219-
220233
# Fixes git "dubious ownership" issues when the volume is mounted with different permissions to the container.
221234
RUN git config --global safe.directory "*"
222235

@@ -225,12 +238,19 @@ RUN mkdir -p /run/postgresql && \
225238
chown -R postgres:postgres /run/postgresql && \
226239
chmod 775 /run/postgresql
227240

241+
# Make app directory accessible to both root and sourcebot user
242+
RUN chown -R sourcebot:sourcebot /app
243+
228244
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
229245
COPY prefix-output.sh ./prefix-output.sh
230246
RUN chmod +x ./prefix-output.sh
231247
COPY entrypoint.sh ./entrypoint.sh
232248
RUN chmod +x ./entrypoint.sh
233249

250+
# Note: for back-compat cases, we do _not_ set the USER directive here.
251+
# Instead, the user can be overridden at runtime with --user flag.
252+
# USER sourcebot
253+
234254
EXPOSE 3000
235255
ENV PORT=3000
236256
ENV HOSTNAME="0.0.0.0"

entrypoint.sh

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ set -e
55
# Disable auto-exporting of variables
66
set +a
77

8+
# Detect if running as root
9+
IS_ROOT=false
10+
if [ "$(id -u)" -eq 0 ]; then
11+
IS_ROOT=true
12+
fi
13+
14+
if [ "$IS_ROOT" = "true" ]; then
15+
echo -e "\e[34m[Info] Running as root user.\e[0m"
16+
else
17+
echo -e "\e[34m[Info] Running as non-root user.\e[0m"
18+
fi
19+
820
# If a CONFIG_PATH is set, resolve the environment overrides from the config file.
921
# The overrides will be written into variables scopped to the current shell. This is
1022
# required in case one of the variables used in this entrypoint is overriden (e.g.,
@@ -83,8 +95,13 @@ fi
8395
# Check if DATABASE_DATA_DIR exists, if not initialize it
8496
if [ "$DATABASE_EMBEDDED" = "true" ] && [ ! -d "$DATABASE_DATA_DIR" ]; then
8597
echo -e "\e[34m[Info] Initializing database at $DATABASE_DATA_DIR...\e[0m"
86-
mkdir -p $DATABASE_DATA_DIR && chown -R postgres:postgres "$DATABASE_DATA_DIR"
87-
su postgres -c "initdb -D $DATABASE_DATA_DIR"
98+
mkdir -p $DATABASE_DATA_DIR
99+
if [ "$IS_ROOT" = "true" ]; then
100+
chown -R postgres:postgres "$DATABASE_DATA_DIR"
101+
su postgres -c "initdb -D $DATABASE_DATA_DIR"
102+
else
103+
initdb -D "$DATABASE_DATA_DIR" -U postgres
104+
fi
88105
fi
89106

90107
# Create the redis data directory if it doesn't exist
@@ -180,13 +197,31 @@ echo "{\"version\": \"$NEXT_PUBLIC_SOURCEBOT_VERSION\", \"install_id\": \"$SOURC
180197

181198
# Start the database and wait for it to be ready before starting any other service
182199
if [ "$DATABASE_EMBEDDED" = "true" ]; then
183-
su postgres -c "postgres -D $DATABASE_DATA_DIR" &
200+
if [ "$IS_ROOT" = "true" ]; then
201+
su postgres -c "postgres -D $DATABASE_DATA_DIR" &
202+
else
203+
postgres -D "$DATABASE_DATA_DIR" &
204+
fi
205+
184206
until pg_isready -h localhost -p 5432 -U postgres; do
185207
echo -e "\e[34m[Info] Waiting for the database to be ready...\e[0m"
186208
sleep 1
209+
210+
# As postgres runs in the background, we must check if it is still
211+
# running, otherwise the "until" loop will be running indefinitely.
212+
if ! pgrep -x "postgres" > /dev/null; then
213+
echo "postgres failed to run"
214+
exit 1
215+
fi
187216
done
217+
218+
if [ "$IS_ROOT" = "false" ]; then
219+
# Running as non-root we need to ensure the postgres account is created.
220+
psql -U postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='postgres'" | grep -q 1 \
221+
|| createuser postgres -s
222+
fi
188223

189-
# Check if the database already exists, and create it if it dne
224+
# Check if the database already exists, and create it if it doesn't exist
190225
EXISTING_DB=$(psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname = 'sourcebot'")
191226

192227
if [ "$EXISTING_DB" = "1" ]; then
@@ -201,7 +236,7 @@ fi
201236
echo -e "\e[34m[Info] Running database migration...\e[0m"
202237
DATABASE_URL="$DATABASE_URL" yarn workspace @sourcebot/db prisma:migrate:prod
203238

204-
# Create the log directory
239+
# Create the log directory if it doesn't exist
205240
mkdir -p /var/log/sourcebot
206241

207242
# Run supervisord

0 commit comments

Comments
 (0)