Repository navigation
Expand file tree
/
Copy pathDockerfile.ubuntu
More file actions
148 lines (127 loc) · 6.26 KB
/
Copy pathDockerfile.ubuntu
File metadata and controls
148 lines (127 loc) · 6.26 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
139
140
141
142
143
144
145
146
147
148
# Locked workspace builds; native addons are compiled on the target platform.
FROM --platform=$BUILDPLATFORM node:24.21.0-bookworm-slim@sha256:2fe369e969550cde8e867afc3fe370b260140cab4a23d467074295b42163d553 AS build
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/*
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-bookworm-slim@sha256:2fe369e969550cde8e867afc3fe370b260140cab4a23d467074295b42163d553 AS backend-deps
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/*
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: Locked OpenBolt gems with the RubyZip 3 WinRM adapter.
FROM ubuntu:24.04@sha256:224a1869083a311ef3f13648a154ba79832fbef6364d31493642ca03082da254 AS bolt-builder
ENV DEBIAN_FRONTEND=noninteractive GEM_HOME=/opt/bolt/tools
RUN apt-get update && apt-get install -y --no-install-recommends \
ruby ruby-dev build-essential libffi-dev ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN gem install bundler -v 2.6.9 --no-document
ENV PATH=/opt/bolt/tools/bin:$PATH \
BUNDLE_PATH=/opt/bolt/bundle \
BUNDLE_GEMFILE=/opt/bolt/Gemfile \
BUNDLE_FROZEN=true
WORKDIR /opt/bolt
COPY docker/bolt/Gemfile docker/bolt/Gemfile.lock ./
COPY docker/bolt/prepare-winrm-fs.rb docker/bolt/test-winrm-rubyzip.rb ./
RUN gem fetch winrm-fs -v 1.3.5 \
&& ruby prepare-winrm-fs.rb winrm-fs-1.3.5.gem \
&& bundle install \
&& bundle binstubs openbolt --path bin \
&& bundle exec ruby test-winrm-rubyzip.rb
# Stage 4: Production image
FROM ubuntu:24.04@sha256:224a1869083a311ef3f13648a154ba79832fbef6364d31493642ca03082da254
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.6.0"
LABEL org.opencontainers.image.vendor="example42"
LABEL org.opencontainers.image.source="https://github.com/example42/pabawi"
# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Set shell to bash with pipefail option
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Use the same pinned Node binary as the dependency build stage.
COPY --from=backend-deps /usr/local/bin/node /usr/local/bin/node
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates libstdc++6 ruby bash openssh-client git coreutils ansible \
&& rm -rf /var/lib/apt/lists/*
# Copy pre-built Bolt gems from builder stage
COPY --from=bolt-builder /opt/bolt /opt/bolt
ENV GEM_HOME=/opt/bolt/tools \
BUNDLE_PATH=/opt/bolt/bundle \
BUNDLE_GEMFILE=/opt/bolt/Gemfile \
BUNDLE_FROZEN=true \
PATH=/opt/bolt/bin:/opt/bolt/tools/bin:$PATH
# Create non-root user
RUN groupadd -g 1001 pabawi && \
useradd -u 1001 -g pabawi -m -s /bin/bash 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"]