Skip to content

Commit 9636cfa

Browse files
authored
Merge pull request #5530 from raft-tech/5512-docker-image-size
Optimize Docker Image Size
2 parents b8ea374 + 8bd35c1 commit 9636cfa

File tree

9 files changed

+183
-53
lines changed

9 files changed

+183
-53
lines changed

.circleci/deployment/commands.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
- disable-npm-audit
142142
- install-nodejs-packages:
143143
app-dir: tdrs-frontend
144+
override-ci-command: npm ci --omit=dev --no-fund
144145
- get-app-deploy-strategy:
145146
appname: <<parameters.frontend-appname>>
146147
- run:

tdrs-backend/.dockerignore

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Git
2+
.git
3+
.gitignore
4+
5+
# Python cache and bytecode
6+
__pycache__
7+
*.py[cod]
8+
*$py.class
9+
*.so
10+
.Python
11+
12+
# Testing and coverage
13+
.coverage
14+
.pytest_cache
15+
htmlcov/
16+
.tox/
17+
.nox/
18+
coverage.xml
19+
*.cover
20+
21+
# IDE and editors
22+
.idea/
23+
.vscode/
24+
*.swp
25+
*.swo
26+
*~
27+
28+
# OS files
29+
.DS_Store
30+
Thumbs.db
31+
32+
# Environment and secrets
33+
.env
34+
.env.*
35+
!.env.example
36+
37+
# Docker files (not needed inside container)
38+
Dockerfile*
39+
docker-compose*.yml
40+
.dockerignore
41+
42+
# Documentation (not needed at runtime)
43+
docs/
44+
*.md
45+
mkdocs.yml
46+
47+
# Test data files
48+
*.TS06
49+
ADS.*
50+
51+
# Local development
52+
vault/
53+
vault_agent/
54+
55+
# Build artifacts
56+
*.egg-info/
57+
dist/
58+
build/

tdrs-backend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
ARG REGISTRY_OWNER=hhs
2-
ARG BASE_TAG=v0.0.6
2+
ARG BASE_TAG=v0.1.0
33

44
FROM ghcr.io/${REGISTRY_OWNER}/tdp-backend-base:${BASE_TAG}
55

tdrs-backend/Dockerfile.base

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,66 @@
22
# docker buildx create --name mybuilder --driver=docker-container --use
33
# docker buildx build -t ghcr.io/raft-tech/tdp-backend-base:dev-02 -f Dockerfile.base . --platform linux/amd64,linux/arm64 --push
44

5+
# =============================================================================
6+
# Stage 1: Builder - Install build dependencies and compile Python packages
7+
# =============================================================================
8+
FROM python:3.10.8-slim-bullseye AS builder
9+
10+
COPY Pipfile Pipfile.lock /tdpapp/
11+
WORKDIR /tdpapp/
12+
13+
# Install build dependencies, Python packages, then clean up in a single layer
14+
RUN apt-get update && \
15+
apt-get install -y --no-install-recommends \
16+
gcc \
17+
graphviz \
18+
graphviz-dev \
19+
libpq-dev \
20+
python3-dev \
21+
curl \
22+
ca-certificates && \
23+
pip install --no-cache-dir --upgrade pip pipenv && \
24+
# If we can remove the '--dev' we will save 200MB. However, so much depends on it that it is easier to keep it for now.
25+
pipenv install --dev --system --deploy && \
26+
rm -rf /var/lib/apt/lists/*
27+
28+
# Download PostgreSQL GPG key in builder stage (so curl isn't needed in runtime)
29+
RUN install -d /pgdg && \
30+
curl -o /pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
31+
32+
# =============================================================================
33+
# Stage 2: Runtime - Minimal image with only runtime dependencies
34+
# =============================================================================
535
FROM python:3.10.8-slim-bullseye
6-
ENV PYTHONUNBUFFERED=1
736

837
ARG user=tdpuser
938
ARG group=tdpuser
1039
ARG uid=1000
1140
ARG gid=1000
41+
42+
ENV PYTHONUNBUFFERED=1
1243
ENV DJANGO_SETTINGS_MODULE=tdpservice.settings.local
1344
ENV DJANGO_CONFIGURATION=Local
14-
# Allows docker to cache installed dependencies between builds
15-
COPY Pipfile Pipfile.lock /tdpapp/
1645

1746
WORKDIR /tdpapp/
1847

19-
# Download latest listing of available packages:
20-
RUN apt-get -y update
21-
# Upgrade already installed packages:
22-
RUN apt-get -y upgrade
23-
# Install packages:
24-
RUN apt-get install -y gcc graphviz graphviz-dev libpq-dev python3-dev vim curl ca-certificates
25-
26-
# Postgres client setup
27-
RUN apt-get update -y && apt-get upgrade -y
28-
RUN apt --purge remove postgresql postgresql-* && apt install -y postgresql-common curl ca-certificates && install -d /usr/share/postgresql-common/pgdg && \
29-
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc && \
30-
sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \
31-
apt -y update && apt -y upgrade && apt install postgresql-client-15 -y
32-
33-
# Install pipenv
34-
RUN pip install --upgrade pip pipenv
35-
RUN pipenv install --dev --system --deploy
36-
37-
RUN groupadd -g ${gid} ${group} && useradd -u ${uid} -g ${group} -s /bin/sh ${user}
48+
# Copy PostgreSQL GPG key from builder
49+
COPY --from=builder /pgdg/apt.postgresql.org.asc /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
50+
51+
# Install only runtime dependencies and PostgreSQL client in a single layer
52+
RUN apt-get update && \
53+
apt-get install -y --no-install-recommends \
54+
libpq5 \
55+
graphviz \
56+
ca-certificates && \
57+
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
58+
apt-get update && \
59+
apt-get install -y --no-install-recommends postgresql-client-15 && \
60+
apt-get clean && \
61+
rm -rf /var/lib/apt/lists/* && \
62+
groupadd -g ${gid} ${group} && \
63+
useradd -u ${uid} -g ${group} -s /bin/sh ${user}
64+
65+
# Copy Python packages from builder stage
66+
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
67+
COPY --from=builder /usr/local/bin /usr/local/bin

tdrs-frontend/.dockerignore

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,53 @@
1+
# Git
12
.git
3+
.gitignore
4+
5+
# Dependencies (will be installed fresh)
26
node_modules
3-
npm-debug.log
7+
8+
# Build output (will be created fresh)
49
build
10+
dist
11+
12+
# Logs
13+
npm-debug.log
14+
yarn-debug.log
15+
yarn-error.log
16+
*.log
17+
18+
# Testing
19+
coverage
20+
.nyc_output
21+
cypress/videos
22+
cypress/screenshots
23+
pa11y-screenshots
24+
25+
# IDE and editors
26+
.idea
27+
.vscode
28+
*.swp
29+
*.swo
30+
*~
31+
32+
# OS files
33+
.DS_Store
34+
Thumbs.db
35+
36+
# Environment files
37+
.env
38+
.env.*
39+
!.env.development
40+
!.env.production
41+
42+
# Docker files (not needed inside container)
43+
Dockerfile*
44+
docker-compose*.yml
45+
.dockerignore
46+
47+
# Documentation
48+
*.md
49+
docs
50+
51+
# Misc
52+
.eslintcache
53+
.prettierignore

tdrs-frontend/Dockerfile

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
ARG REGISTRY_OWNER=hhs
2-
ARG BASE_TAG=v0.1.0
2+
ARG BASE_TAG=v0.2.0
33

44
FROM ghcr.io/${REGISTRY_OWNER}/tdp-frontend-base:${BASE_TAG} AS localdev
55

@@ -13,19 +13,19 @@ FROM localdev AS build
1313
RUN npm run build:development
1414

1515
# ---
16-
# Stage 2: Serve over nginx
16+
# Stage 2: Serve over nginx (minimal production image)
1717
FROM nginx:1.25-alpine AS nginx
1818

19-
# Copy the build folder (from the result of the Stage 1 "build" stage) to the root of nginx (www)
19+
# Copy only the built static files from build stage
2020
COPY --from=build /home/node/app/build /usr/share/nginx/html
2121

22-
# To using react router
23-
# it's necessary to overwrite the default nginx configurations:
24-
# remove default nginx configuration file, replace with custom conf
25-
RUN rm /etc/nginx/conf.d/default.conf
26-
RUN rm /etc/nginx/nginx.conf
22+
# Copy nginx configuration
2723
COPY nginx/local/default.conf.template /etc/nginx/default.conf.template
2824
COPY nginx/local/locations.conf /etc/nginx/locations.conf
29-
#COPY nginx/local/under_maintenance.html /etc/nginx/under_maintenance.html
3025
COPY nginx/src/503.html /usr/share/nginx/html/503_.html
3126
COPY nginx/src/static/ /usr/share/nginx/html/static/
27+
28+
# Remove default nginx config and set up custom config in single layer
29+
RUN rm -f /etc/nginx/conf.d/default.conf /etc/nginx/nginx.conf && \
30+
chown -R nginx:nginx /usr/share/nginx/html && \
31+
chmod -R 755 /usr/share/nginx/html

tdrs-frontend/Dockerfile.base

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
2-
# Stage 0: Create the app directory, install dependencies, and copy in the source code
1+
# Base image for frontend builds
2+
# Note: Chromium/Puppeteer is NOT needed here - pa11y tests run on CI machine directly
33
FROM node:16.13-alpine3.14 AS localdev
44

5-
# Due to M1 issues found here, adding solution:
6-
# https://stackoverflow.com/questions/69983063/
7-
RUN apk add chromium
8-
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
9-
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
10-
115
USER node
126

13-
147
RUN mkdir /home/node/app/ && chown -R node:node /home/node/app
158
WORKDIR /home/node/app
169

@@ -19,10 +12,11 @@ WORKDIR /home/node/app
1912
# when code changes occur
2013
COPY --chown=node:node package.json package-lock.json ./
2114

22-
# Disable npm audit
23-
RUN npm set audit false
24-
# Install npm packages directly from package-lock.json <https://docs.npmjs.com/cli/v8/commands/npm-ci>
25-
RUN npm ci
15+
# Install all dependencies (devDependencies needed because @redux-devtools/extension is imported in src/configureStore.js)
16+
# TODO: Move @redux-devtools/extension to dependencies in package.json, then use --omit=dev to save ~500MB
17+
RUN npm set audit false && \
18+
npm ci --omit=dev --no-fund && \
19+
npm cache clean --force
2620

2721
ENV PORT=80
2822
EXPOSE 80

tdrs-frontend/package-lock.json

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tdrs-frontend/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"axios": "^1.7.7",
1616
"classnames": "^2.5.1",
1717
"detect-file-encoding-and-language": "^2.4.0",
18+
"@faker-js/faker": "^9.2.0",
1819
"file-type-checker": "^1.1.2",
1920
"history": "^5.3.0",
2021
"include-media": "^2.0.0",
@@ -29,14 +30,15 @@
2930
"react-router-dom": "^6.28.0",
3031
"react-scripts": "^5.0.1",
3132
"redux": "^5.0.1",
33+
"@redux-devtools/extension": "^3.3.0",
3234
"redux-thunk": "^3.1.0",
3335
"seamless-immutable": "^7.1.4",
3436
"uuid": "^11.0.3"
3537
},
3638
"scripts": {
3739
"start": "SASS_PATH=\"`cd \"./src\";pwd`:./node_modules/@uswds:./node_modules/@uswds/uswds/packages\" react-scripts start",
3840
"start:ci": "CI=true HOST=localhost BROWSER=none npm run start",
39-
"build": "sh -ac '. ./.env.${REACT_APP_ENV}; SASS_PATH=\"`cd \"./src\";pwd`:./node_modules/@uswds:./node_modules/@uswds/uswds/packages\" react-scripts build'",
41+
"build": "sh -ac '. ./.env.${REACT_APP_ENV}; DISABLE_ESLINT_PLUGIN=true SASS_PATH=\"`cd \"./src\";pwd`:./node_modules/@uswds:./node_modules/@uswds/uswds/packages\" react-scripts build'",
4042
"build:development": "REACT_APP_ENV=development npm run build",
4143
"build:production": "REACT_APP_ENV=production npm run build",
4244
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" react-scripts test",
@@ -68,8 +70,6 @@
6870
"@badeball/cypress-cucumber-preprocessor": "^21.0.3",
6971
"@cucumber/pretty-formatter": "^2.2.0",
7072
"@cypress/webpack-preprocessor": "^6.0.2",
71-
"@faker-js/faker": "^9.2.0",
72-
"@redux-devtools/extension": "^3.3.0",
7373
"@testing-library/dom": "^10.4.0",
7474
"@testing-library/jest-dom": "^6.6.3",
7575
"@testing-library/react": "^16.0.1",

0 commit comments

Comments
 (0)