Skip to content

Commit 76509b8

Browse files
committed
fix: implement non-root user in Docker containers
- Add appuser (UID 1000) in builder stage - Copy passwd file to scratch image - Use USER directive to run as non-root user - Fix docker-compose.yml to use YAML anchors properly - Add Dockerfile.dev for development with shell access - Addresses PR review comment about security
1 parent 429417f commit 76509b8

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

Dockerfile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ FROM golang:1.23-alpine AS builder
44
# Install git and ca-certificates (needed for fetching dependencies and HTTPS)
55
RUN apk add --no-cache git ca-certificates tzdata
66

7+
# Create a non-root user for the final stage
8+
RUN adduser -D -u 1000 appuser
9+
710
# Set the working directory
811
WORKDIR /app
912

@@ -36,11 +39,14 @@ COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
3639
# Copy timezone data
3740
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
3841

42+
# Add a minimal /etc/passwd file to support non-root user
43+
COPY --from=builder /etc/passwd /etc/passwd
44+
3945
# Copy the binary
4046
COPY --from=builder /app/articulate-parser /articulate-parser
4147

42-
# Create a non-root user (note: in scratch image, we can't create users dynamically)
43-
# The binary will run as root in scratch, which is acceptable for containers
48+
# Switch to non-root user (appuser with UID 1000)
49+
USER appuser
4450

4551
# Set the binary as entrypoint
4652
ENTRYPOINT ["/articulate-parser"]

Dockerfile.dev

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Development Dockerfile with shell access
2+
# Uses Alpine instead of scratch for debugging
3+
4+
# Build stage - same as production
5+
FROM golang:1.23-alpine AS builder
6+
7+
# Install git and ca-certificates (needed for fetching dependencies and HTTPS)
8+
RUN apk add --no-cache git ca-certificates tzdata
9+
10+
# Create a non-root user
11+
RUN adduser -D -u 1000 appuser
12+
13+
# Set the working directory
14+
WORKDIR /app
15+
16+
# Copy go mod files
17+
COPY go.mod go.sum ./
18+
19+
# Download dependencies
20+
RUN go mod download
21+
22+
# Copy source code
23+
COPY . .
24+
25+
# Build the application
26+
# Disable CGO for a fully static binary
27+
# Use linker flags to reduce binary size and embed version info
28+
ARG VERSION=dev
29+
ARG BUILD_TIME
30+
ARG GIT_COMMIT
31+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
32+
-ldflags="-s -w -X github.com/kjanat/articulate-parser/internal/version.Version=${VERSION} -X github.com/kjanat/articulate-parser/internal/version.BuildTime=${BUILD_TIME} -X github.com/kjanat/articulate-parser/internal/version.GitCommit=${GIT_COMMIT}" \
33+
-o articulate-parser \
34+
./main.go
35+
36+
# Development stage - uses Alpine for shell access
37+
FROM alpine:3.19
38+
39+
# Install minimal dependencies
40+
RUN apk add --no-cache ca-certificates tzdata
41+
42+
# Copy the binary
43+
COPY --from=builder /app/articulate-parser /articulate-parser
44+
45+
# Copy the non-root user configuration
46+
COPY --from=builder /etc/passwd /etc/passwd
47+
48+
# Switch to non-root user
49+
USER appuser
50+
51+
# Set the binary as entrypoint
52+
ENTRYPOINT ["/articulate-parser"]
53+
54+
# Default command shows help
55+
CMD ["--help"]
56+
57+
# Add labels for metadata
58+
LABEL org.opencontainers.image.title="Articulate Parser (Dev)"
59+
LABEL org.opencontainers.image.description="Development version of Articulate Parser with shell access"
60+
LABEL org.opencontainers.image.vendor="kjanat"
61+
LABEL org.opencontainers.image.licenses="MIT"
62+
LABEL org.opencontainers.image.source="https://github.com/kjanat/articulate-parser"
63+
LABEL org.opencontainers.image.documentation="https://github.com/kjanat/articulate-parser/blob/master/README.md"

docker-compose.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
services:
2-
articulate-parser:
2+
articulate-parser: &articulate-parser
33
build:
44
context: .
55
dockerfile: Dockerfile
@@ -19,15 +19,21 @@ services:
1919

2020
# Service for processing files with volume mounts
2121
parser-with-files:
22-
extends: articulate-parser
22+
<<: *articulate-parser
2323
volumes:
2424
- ./input:/input:ro
2525
- ./output:/output
2626
command: ["/input/sample.json", "markdown", "/output/result.md"]
2727

2828
# Service for development - with shell access
2929
parser-dev:
30-
extends: articulate-parser
30+
build:
31+
context: .
32+
dockerfile: Dockerfile.dev
33+
image: articulate-parser:dev
34+
volumes:
35+
- .:/workspace
36+
working_dir: /workspace
3137
entrypoint: ["/bin/sh"]
3238
command: ["-c", "while true; do sleep 30; done"]
33-
# This won't work with scratch image, but useful for debugging builds
39+
# Uses Dockerfile.dev with Alpine base instead of scratch for shell access

0 commit comments

Comments
 (0)