Repository navigation
Expand file tree
/
Copy pathDockerfile.alpine
More file actions
138 lines (117 loc) · 5.6 KB
/
Copy pathDockerfile.alpine
File metadata and controls
138 lines (117 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Locked workspace builds; native addons are compiled on the target platform.
FROM --platform=$BUILDPLATFORM node:24.21.0-alpine3.23@sha256:159fe64649038c30f8cc1ec4be3af3a6e93e3648678c31294e2c5058dbeb99f3 AS build
WORKDIR /app
RUN apk add --no-cache python3 make g++
COPY package.json package-lock.json .npmrc ./
COPY backend/package.json ./backend/package.json
COPY frontend/package.json ./frontend/package.json
COPY scripts/supply-chain/install-approved.mjs ./scripts/supply-chain/install-approved.mjs
ENV npm_config_build_from_source=true npm_config_nodedir=/usr/local
RUN npm ci --ignore-scripts --no-audit --no-fund && npm run install:approved
COPY backend/ ./backend/
COPY frontend/ ./frontend/
COPY scripts/compilation/backend.mjs ./scripts/compilation/backend.mjs
RUN npm run build:frontend && npm run build:backend
RUN npm sbom --workspace=frontend --omit=dev --sbom-format=cyclonedx > frontend.cdx.json
FROM node:24.21.0-alpine3.23@sha256:159fe64649038c30f8cc1ec4be3af3a6e93e3648678c31294e2c5058dbeb99f3 AS backend-deps
WORKDIR /app
RUN apk add --no-cache python3 make g++
COPY package.json package-lock.json .npmrc ./
COPY backend/package.json ./backend/package.json
COPY frontend/package.json ./frontend/package.json
COPY scripts/supply-chain/install-approved.mjs ./scripts/supply-chain/install-approved.mjs
ENV npm_config_build_from_source=true npm_config_nodedir=/usr/local
RUN npm ci --workspace=backend --omit=dev --ignore-scripts --no-audit --no-fund && npm run install:approved
# Keep both hoisted and workspace-local packages in their locked locations.
RUN mkdir -p backend/node_modules
# Stage 3: Install Bolt CLI gems in a builder stage
FROM node:24.21.0-alpine3.23@sha256:159fe64649038c30f8cc1ec4be3af3a6e93e3648678c31294e2c5058dbeb99f3 AS bolt-builder
# hadolint ignore=DL3018
RUN apk add --no-cache \
ruby \
ruby-dev \
build-base \
linux-headers \
&& gem install openbolt -v 5.1.0 --no-document
# Stage 4: Production image
FROM node:24.21.0-alpine3.23@sha256:159fe64649038c30f8cc1ec4be3af3a6e93e3648678c31294e2c5058dbeb99f3
ARG TARGETPLATFORM
ARG BUILDPLATFORM
# Add metadata labels
LABEL org.opencontainers.image.title="Pabawi"
LABEL org.opencontainers.image.description="Puppet Ansible Bolt Awesome Web Interface"
LABEL org.opencontainers.image.version="1.5.0"
LABEL org.opencontainers.image.vendor="example42"
LABEL org.opencontainers.image.source="https://github.com/example42/pabawi"
# Install only runtime dependencies, without build tools in the final image
# hadolint ignore=DL3018
RUN apk add --no-cache --upgrade libssl3 libcrypto3 \
&& apk add --no-cache \
ruby ruby-syslog \
bash \
openssh-client \
git \
coreutils
# The base image ships a global npm install that the runtime never uses
# (the app only ever runs `node dist/server.js`); drop it so its vendored
# dependencies (e.g. brace-expansion, tar, ip-address) don't ship either.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack
# Copy pre-built Bolt gems from builder stage (avoids build-base in final image)
COPY --from=bolt-builder /usr/lib/ruby/gems /usr/lib/ruby/gems
COPY --from=bolt-builder /usr/bin/bolt /usr/bin/bolt
# Create non-root user
RUN addgroup -g 1001 -S pabawi && \
adduser -u 1001 -S pabawi -G pabawi
# Create application directory
WORKDIR /app/backend
# Copy built backend
COPY --from=backend-deps /app/package.json /app/.npmrc /app/
COPY --from=backend-deps /app/package-lock.json /app/root-lock.json
COPY --from=build /app/frontend.cdx.json /app/sbom/frontend.cdx.json
COPY --from=build --chown=pabawi:pabawi /app/backend/dist ./dist
COPY --from=backend-deps --chown=pabawi:pabawi /app/node_modules /app/node_modules
COPY --from=backend-deps --chown=pabawi:pabawi /app/backend/node_modules ./node_modules
COPY --from=build --chown=pabawi:pabawi /app/backend/package.json ./
# Copy database migrations (not copied by TypeScript compiler)
COPY --from=build --chown=pabawi:pabawi /app/backend/src/database/migrations ./dist/database/migrations
# Copy built frontend to public directory
COPY --from=build --chown=pabawi:pabawi /app/frontend/dist ./public
# Create /opt/pabawi directory tree for all runtime data
RUN mkdir -p /opt/pabawi/data \
/opt/pabawi/bolt-project \
/opt/pabawi/control-repo \
/opt/pabawi/ansible \
/opt/pabawi/certs \
/opt/pabawi/ssh \
&& chown -R pabawi:pabawi /opt/pabawi
# Copy entrypoint script (shared across all Dockerfiles)
COPY scripts/docker-entrypoint.sh /app/docker-entrypoint.sh
RUN sed -i 's/\r$//' /app/docker-entrypoint.sh && chmod +x /app/docker-entrypoint.sh
# Switch to non-root user
USER pabawi
ENTRYPOINT ["/app/docker-entrypoint.sh"]
# Expose port
EXPOSE 3000
# Set environment variables
ENV NODE_ENV=production \
PORT=3000 \
HOST=0.0.0.0 \
DATABASE_PATH=/opt/pabawi/data/pabawi.db \
BOLT_PROJECT_PATH=/opt/pabawi/bolt-project \
HIERA_CONTROL_REPO_PATH=/opt/pabawi/control-repo \
ANSIBLE_PROJECT_PATH=/opt/pabawi/ansible \
SSH_CONFIG_PATH=/opt/pabawi/ssh/config \
SSH_DEFAULT_KEY=/opt/pabawi/ssh/id_rsa \
# Integration settings (disabled by default)
PUPPETDB_ENABLED=false \
PUPPETSERVER_ENABLED=false \
HIERA_ENABLED=false \
ANSIBLE_ENABLED=false \
PROXMOX_ENABLED=false \
AWS_ENABLED=false \
SSH_ENABLED=false
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# Start the application
CMD ["node", "dist/server.js"]