Skip to content

Commit dc78c11

Browse files
committed
implement shared base stages for faster builds and better caching
1 parent b6d304d commit dc78c11

4 files changed

Lines changed: 195 additions & 46 deletions

File tree

.dockerignore

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,75 @@
1+
# ================================================================
2+
# Docker Build Context Optimization
3+
# Exclude unnecessary files to reduce build context size and improve performance
4+
# ================================================================
5+
6+
# Git and version control
7+
.git
8+
.gitignore
9+
.gitattributes
10+
.gitmodules
11+
12+
# Documentation and markdown files (except essential ones)
13+
*.md
14+
!README.md
15+
docs/
16+
site/
17+
18+
# Development files
19+
.vscode/
20+
.idea/
21+
*.swp
22+
*.swo
23+
*~
24+
25+
# OS generated files
26+
.DS_Store
27+
.DS_Store?
28+
._*
29+
.Spotlight-V100
30+
.Trashes
31+
ehthumbs.db
32+
Thumbs.db
33+
34+
# Logs and temporary files
35+
*.log
36+
*.tmp
37+
*.temp
38+
mem_log.txt
39+
coverage.out
40+
41+
# Node.js (keep essential files, exclude build artifacts)
142
**/node_modules
243
**/build
3-
docs
4-
contrib
44+
internal/webui/.yarn/
45+
internal/webui/yarn-error.log
46+
internal/webui/npm-debug.log*
47+
internal/webui/lerna-debug.log*
48+
49+
# Go build artifacts (exclude from context, but keep source)
50+
pgwatch
51+
cmd/pgwatch/pgwatch
52+
*.exe
53+
54+
# Test files and test data
55+
*_test.go
56+
**/*_test.go
57+
testdata/
58+
59+
# Docker artifacts
60+
docker-compose*.yml
61+
compose*.yml
62+
63+
# CI/CD (GitHub Actions can access these separately)
64+
.github/
65+
66+
# Local development tools
67+
etcdctl.exe
68+
.env
69+
.env.local
70+
.env.*.local
71+
72+
# Other build artifacts
73+
dist/
74+
out/
75+
contrib/
Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
name: Docker Manual Multi-Registry Build
1+
name: Docker Multi-Registry Build
22
permissions:
33
contents: read
4+
packages: write
5+
46
on:
57
workflow_dispatch:
68
inputs:
@@ -29,24 +31,42 @@ jobs:
2931
outputs:
3032
registry: ${{ steps.config.outputs.registry }}
3133
should-push: ${{ steps.config.outputs.should-push }}
34+
cache-key: ${{ steps.config.outputs.cache-key }}
35+
webui-hash: ${{ steps.config.outputs.webui-hash }}
36+
go-hash: ${{ steps.config.outputs.go-hash }}
3237
steps:
38+
- name: Check out source code
39+
uses: actions/checkout@v4
40+
3341
- name: Configure registry and push settings
3442
id: config
3543
run: |
36-
# Manual workflow: use inputs directly
3744
REGISTRY="${{ github.event.inputs.registry }}"
3845
SHOULD_PUSH="${{ github.event.inputs.push }}"
3946
47+
# Create cache keys based on content hashes for better cache efficiency
48+
WEBUI_HASH=$(find internal/webui -name "*.json" -o -name "*.lock" | sort | xargs cat | sha256sum | cut -d' ' -f1 | cut -c1-12)
49+
GO_HASH=$(cat go.mod go.sum | sha256sum | cut -d' ' -f1 | cut -c1-12)
50+
CACHE_KEY="${{ github.ref_name }}-$(date +%Y%m%d)"
51+
4052
echo "registry=$REGISTRY" >> $GITHUB_OUTPUT
4153
echo "should-push=$SHOULD_PUSH" >> $GITHUB_OUTPUT
54+
echo "cache-key=$CACHE_KEY" >> $GITHUB_OUTPUT
55+
echo "webui-hash=$WEBUI_HASH" >> $GITHUB_OUTPUT
56+
echo "go-hash=$GO_HASH" >> $GITHUB_OUTPUT
4257
4358
echo "🚀 Registry: $REGISTRY"
4459
echo "📤 Push: $SHOULD_PUSH"
60+
echo "🔧 Cache Key: $CACHE_KEY"
61+
echo "🔧 WebUI Hash: $WEBUI_HASH"
62+
echo "🔧 Go Hash: $GO_HASH"
4563
4664
docker:
47-
name: Build Docker Images
65+
name: Build Docker Images
4866
needs: prepare
4967
strategy:
68+
# Build sequentially to allow cache sharing between images
69+
max-parallel: 1
5070
fail-fast: false
5171
matrix:
5272
image: [
@@ -77,7 +97,7 @@ jobs:
7797
echo "password=${{ secrets.DOCKER_PASSWORD }}" >> $GITHUB_OUTPUT
7898
fi
7999
80-
- name: Build and push to selected registry
100+
- name: Build and push with optimized caching
81101
uses: ./.github/actions/build-docker
82102
with:
83103
dockerfile: ${{ matrix.image.file }}
@@ -87,7 +107,7 @@ jobs:
87107
password: ${{ steps.creds.outputs.password }}
88108
platforms: linux/amd64,linux/arm64
89109
push: ${{ needs.prepare.outputs.should-push }}
90-
cache-scope: ${{ needs.prepare.outputs.registry }}-${{ matrix.image.name }}
110+
cache-scope: ${{ needs.prepare.outputs.registry }}-${{ matrix.image.name }}-${{ needs.prepare.outputs.webui-hash }}-${{ needs.prepare.outputs.go-hash }}
91111
build-args: |
92112
GIT_HASH=${{ steps.meta.outputs.GIT_HASH }}
93113
GIT_TIME=${{ steps.meta.outputs.GIT_TIME }}
@@ -105,13 +125,17 @@ jobs:
105125
echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY
106126
echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY
107127
echo "| Registry | \`${{ needs.prepare.outputs.registry }}\` |" >> $GITHUB_STEP_SUMMARY
108-
echo "| Push Enabled | ${{ needs.prepare.outputs.should-push }} |" >> $GITHUB_STEP_SUMMARY
128+
echo "| Push Enabled | \`${{ needs.prepare.outputs.should-push }}\` |" >> $GITHUB_STEP_SUMMARY
129+
echo "| Cache Key | \`${{ needs.prepare.outputs.cache-key }}\` |" >> $GITHUB_STEP_SUMMARY
130+
echo "| WebUI Hash | \`${{ needs.prepare.outputs.webui-hash }}\` |" >> $GITHUB_STEP_SUMMARY
131+
echo "| Go Hash | \`${{ needs.prepare.outputs.go-hash }}\` |" >> $GITHUB_STEP_SUMMARY
109132
echo "| Trigger | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
110133
echo "| Ref | \`${{ github.ref }}\` |" >> $GITHUB_STEP_SUMMARY
111-
echo "| Images | \`cybertecpostgresql/pgwatch\`, \`cybertecpostgresql/pgwatch-demo\` |" >> $GITHUB_STEP_SUMMARY
112134
113135
if [ "${{ needs.docker.result }}" = "success" ]; then
114-
echo "✅ All Docker builds completed successfully!" >> $GITHUB_STEP_SUMMARY
136+
echo "" >> $GITHUB_STEP_SUMMARY
137+
echo "✅ **All Docker builds completed successfully!**" >> $GITHUB_STEP_SUMMARY
115138
else
116-
echo "❌ Some Docker builds failed. Check the logs above." >> $GITHUB_STEP_SUMMARY
139+
echo "" >> $GITHUB_STEP_SUMMARY
140+
echo "❌ **Some Docker builds failed. Check the logs above.**" >> $GITHUB_STEP_SUMMARY
117141
fi

docker/Dockerfile

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,67 @@
1+
# ================================================================
2+
# PRODUCTION PGWATCH IMAGE - OPTIMIZED VERSION
3+
# Uses shared base stages for faster builds and better caching
4+
# ================================================================
5+
16
# ----------------------------------------------------------------
2-
# 1. Build Web UI
7+
# 1. WebUI Dependencies (cached separately for better performance)
38
# ----------------------------------------------------------------
4-
FROM node:22 AS uibuilder
5-
ADD internal/webui /webui
6-
RUN cd webui && yarn install --network-timeout 100000 && yarn build
9+
FROM node:22 AS webui-deps
10+
WORKDIR /webui
11+
# Copy only package files first for optimal layer caching
12+
COPY internal/webui/package.json internal/webui/yarn.lock ./
13+
RUN yarn install --network-timeout 100000 --frozen-lockfile
714

815
# ----------------------------------------------------------------
9-
# 2. Build gatherer
16+
# 2. WebUI Builder (rebuilds only when source changes)
1017
# ----------------------------------------------------------------
11-
FROM golang:1.24 AS builder
12-
13-
ARG VERSION
14-
ARG GIT_HASH
15-
ARG GIT_TIME
18+
FROM webui-deps AS webui-builder
19+
# Copy source files and build
20+
COPY internal/webui/ ./
21+
RUN yarn build
1622

23+
# ----------------------------------------------------------------
24+
# 3. Go Dependencies and Tools (cached separately)
25+
# ----------------------------------------------------------------
26+
FROM golang:1.24 AS go-deps
1727
# Install protoc and required tools for protobuf generation
1828
RUN apt-get update && apt-get install -y protobuf-compiler && rm -rf /var/lib/apt/lists/*
1929
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
2030
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
2131

22-
COPY . /pgwatch
23-
COPY --from=uibuilder /webui/build /pgwatch/internal/webui/build
24-
RUN cd /pgwatch \
25-
&& go generate ./api/pb/ \
26-
&& CGO_ENABLED=0 go build -ldflags "\
32+
# Pre-download Go modules for better caching
33+
WORKDIR /pgwatch
34+
COPY go.mod go.sum ./
35+
RUN go mod download
36+
37+
# ----------------------------------------------------------------
38+
# 4. Go Builder (application compilation)
39+
# ----------------------------------------------------------------
40+
FROM go-deps AS go-builder
41+
42+
ARG VERSION
43+
ARG GIT_HASH
44+
ARG GIT_TIME
45+
46+
# Copy source code
47+
COPY . .
48+
# Copy built WebUI from previous stage
49+
COPY --from=webui-builder /webui/build ./internal/webui/build
50+
51+
# Generate protobuf and build the application
52+
RUN go generate ./api/pb/ && \
53+
CGO_ENABLED=0 go build -ldflags "\
2754
-X 'main.commit=${GIT_HASH}' \
2855
-X 'main.date=${GIT_TIME}' \
2956
-X 'main.version=${VERSION}'" ./cmd/pgwatch
3057

3158
# ----------------------------------------------------------------
32-
# 3. Build the final image
59+
# 5. Final production image
3360
# ----------------------------------------------------------------
3461
FROM alpine
3562

3663
# Copy over the compiled gatherer
37-
COPY --from=builder /pgwatch/pgwatch /pgwatch/
64+
COPY --from=go-builder /pgwatch/pgwatch /pgwatch/
3865
COPY internal/metrics/metrics.yaml /pgwatch/metrics/metrics.yaml
3966

4067
# Admin UI for configuring servers to be monitored

docker/demo/Dockerfile

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,67 @@
1+
# ================================================================
2+
# DEMO PGWATCH IMAGE - OPTIMIZED VERSION
3+
# Uses shared base stages + PostgreSQL/Grafana demo setup
4+
# ================================================================
5+
16
# ----------------------------------------------------------------
2-
# 1. Build Web UI
7+
# 1. WebUI Dependencies (cached separately for better performance)
38
# ----------------------------------------------------------------
4-
FROM node:22 AS uibuilder
5-
COPY internal/webui /webui
6-
RUN cd webui && yarn install --network-timeout 100000 && yarn build
9+
FROM node:22 AS webui-deps
10+
WORKDIR /webui
11+
# Copy only package files first for optimal layer caching
12+
COPY internal/webui/package.json internal/webui/yarn.lock ./
13+
RUN yarn install --network-timeout 100000 --frozen-lockfile
714

815
# ----------------------------------------------------------------
9-
# 2. Build gatherer
16+
# 2. WebUI Builder (rebuilds only when source changes)
1017
# ----------------------------------------------------------------
11-
FROM golang:1.24 AS builder
12-
13-
ARG VERSION
14-
ARG GIT_HASH
15-
ARG GIT_TIME
18+
FROM webui-deps AS webui-builder
19+
# Copy source files and build
20+
COPY internal/webui/ ./
21+
RUN yarn build
1622

23+
# ----------------------------------------------------------------
24+
# 3. Go Dependencies and Tools (cached separately)
25+
# ----------------------------------------------------------------
26+
FROM golang:1.24 AS go-deps
1727
# Install protoc and required tools for protobuf generation
1828
RUN apt-get update && apt-get install -y protobuf-compiler && rm -rf /var/lib/apt/lists/*
1929
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
2030
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
2131

22-
COPY . /pgwatch
23-
COPY --from=uibuilder /webui/build /pgwatch/internal/webui/build
24-
RUN cd /pgwatch \
25-
&& go generate ./api/pb/ \
26-
&& CGO_ENABLED=0 go build -ldflags "\
32+
# Pre-download Go modules for better caching
33+
WORKDIR /pgwatch
34+
COPY go.mod go.sum ./
35+
RUN go mod download
36+
37+
# ----------------------------------------------------------------
38+
# 4. Go Builder (application compilation)
39+
# ----------------------------------------------------------------
40+
FROM go-deps AS go-builder
41+
42+
ARG VERSION
43+
ARG GIT_HASH
44+
ARG GIT_TIME
45+
46+
# Copy source code
47+
COPY . .
48+
# Copy built WebUI from previous stage
49+
COPY --from=webui-builder /webui/build ./internal/webui/build
50+
51+
# Generate protobuf and build the application
52+
RUN go generate ./api/pb/ && \
53+
CGO_ENABLED=0 go build -ldflags "\
2754
-X 'main.commit=${GIT_HASH}' \
2855
-X 'main.date=${GIT_TIME}' \
2956
-X 'main.version=${VERSION}'" ./cmd/pgwatch
3057

3158
# ----------------------------------------------------------------
32-
# 3. Build the final image
59+
# 5. Demo Image with PostgreSQL + Grafana
3360
# ----------------------------------------------------------------
34-
FROM postgres:17-bullseye AS releaser
61+
FROM postgres:17-bullseye AS demo
3562

3663
# Copy over the compiled gatherer
37-
COPY --from=builder /pgwatch/pgwatch /pgwatch/
64+
COPY --from=go-builder /pgwatch/pgwatch /pgwatch/
3865
COPY internal/metrics/metrics.yaml /pgwatch/metrics/metrics.yaml
3966

4067
# Install TimescaleDB and extensions

0 commit comments

Comments
 (0)