|
1 | 1 | # ========= BUILD FRONTEND ========= |
2 | | -FROM --platform=$BUILDPLATFORM node:24-alpine AS frontend-build |
3 | | - |
| 2 | +FROM --platform=linux/arm64 node:24-alpine AS frontend-build |
4 | 3 | WORKDIR /frontend |
5 | 4 |
|
6 | | -# Add version for the frontend build |
7 | 5 | ARG APP_VERSION=dev |
8 | 6 | ENV VITE_APP_VERSION=$APP_VERSION |
9 | 7 |
|
10 | 8 | COPY frontend/package.json frontend/package-lock.json ./ |
11 | 9 | RUN npm ci |
12 | 10 | COPY frontend/ ./ |
13 | 11 |
|
14 | | -# Copy .env file (with fallback to .env.production.example) |
15 | | -RUN if [ ! -f .env ]; then \ |
16 | | - if [ -f .env.production.example ]; then \ |
17 | | - cp .env.production.example .env; \ |
18 | | - fi; \ |
| 12 | +RUN if [ ! -f .env ] && [ -f .env.production.example ]; then \ |
| 13 | + cp .env.production.example .env; \ |
19 | 14 | fi |
20 | 15 |
|
21 | 16 | RUN npm run build |
22 | 17 |
|
23 | 18 | # ========= BUILD BACKEND ========= |
24 | | -FROM --platform=$BUILDPLATFORM golang:1.23.3 AS backend-build |
25 | | - |
26 | | -# Install Go public tools needed in runtime |
27 | | -RUN curl -fsSL https://raw.githubusercontent.com/pressly/goose/master/install.sh | sh |
28 | | -RUN go install github.com/swaggo/swag/cmd/ [email protected] |
29 | | - |
30 | | -# Set working directory |
| 19 | +FROM --platform=linux/arm64 golang:1.23.3 AS backend-build |
31 | 20 | WORKDIR /app |
32 | 21 |
|
33 | | -# Install Go dependencies |
| 22 | +# Install Go tools for ARM64 |
| 23 | +RUN go install github.com/pressly/goose/v3/cmd/goose@latest \ |
| 24 | + && go install github.com/swaggo/swag/cmd/ [email protected] |
| 25 | + |
34 | 26 | COPY backend/go.mod backend/go.sum ./ |
35 | 27 | RUN go mod download |
36 | 28 |
|
37 | | -# Create required directories for embedding |
| 29 | +# Copy frontend build into backend |
38 | 30 | RUN mkdir -p /app/ui/build |
39 | | - |
40 | | -# Copy frontend build output for embedding |
41 | 31 | COPY --from=frontend-build /frontend/dist /app/ui/build |
42 | 32 |
|
43 | | -# Generate Swagger documentation |
44 | 33 | COPY backend/ ./ |
45 | 34 | RUN swag init -d . -g cmd/main.go -o swagger |
46 | 35 |
|
47 | | -# Compile the backend |
48 | | -ARG TARGETOS |
49 | | -ARG TARGETARCH |
50 | | -ARG TARGETVARIANT |
51 | | -RUN CGO_ENABLED=0 \ |
52 | | - GOOS=$TARGETOS \ |
53 | | - GOARCH=$TARGETARCH \ |
| 36 | +RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \ |
54 | 37 | go build -o /app/main ./cmd/main.go |
55 | 38 |
|
56 | | - |
57 | 39 | # ========= RUNTIME ========= |
58 | | -FROM --platform=$TARGETPLATFORM debian:bookworm-slim |
| 40 | +FROM --platform=linux/arm64 debian:bookworm-slim |
59 | 41 |
|
60 | | -# Add version metadata to runtime image |
61 | 42 | ARG APP_VERSION=dev |
62 | 43 | LABEL org.opencontainers.image.version=$APP_VERSION |
63 | 44 | ENV APP_VERSION=$APP_VERSION |
64 | 45 |
|
65 | | -# Install PostgreSQL server and client tools (versions 13-17) |
66 | | -RUN apt-get update && apt-get install -y --no-install-recommends \ |
67 | | - wget ca-certificates gnupg lsb-release sudo gosu && \ |
68 | | - wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \ |
69 | | - echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \ |
70 | | - > /etc/apt/sources.list.d/pgdg.list && \ |
71 | | - apt-get update && \ |
72 | | - apt-get install -y --no-install-recommends \ |
73 | | - postgresql-17 postgresql-client-13 postgresql-client-14 postgresql-client-15 \ |
74 | | - postgresql-client-16 postgresql-client-17 && \ |
75 | | - rm -rf /var/lib/apt/lists/* |
76 | | - |
77 | | -# Create postgres user and set up directories |
78 | | -RUN useradd -m -s /bin/bash postgres || true && \ |
79 | | - mkdir -p /postgresus-data/pgdata && \ |
80 | | - chown -R postgres:postgres /postgresus-data/pgdata |
| 46 | +# Install PostgreSQL clients (13–17) and runtime deps |
| 47 | +RUN apt-get update \ |
| 48 | + && apt-get install -y --no-install-recommends wget ca-certificates gnupg lsb-release sudo gosu \ |
| 49 | + && echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \ |
| 50 | + > /etc/apt/sources.list.d/pgdg.list \ |
| 51 | + && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor \ |
| 52 | + > /etc/apt/trusted.gpg.d/postgresql.gpg \ |
| 53 | + && apt-get update \ |
| 54 | + && apt-get install -y --no-install-recommends \ |
| 55 | + postgresql-17 \ |
| 56 | + postgresql-client-13 \ |
| 57 | + postgresql-client-14 \ |
| 58 | + postgresql-client-15 \ |
| 59 | + postgresql-client-16 \ |
| 60 | + postgresql-client-17 \ |
| 61 | + && rm -rf /var/lib/apt/lists/* |
| 62 | + |
| 63 | +# Create data dir and set ownership (postgres user already exists) |
| 64 | +RUN mkdir -p /postgresus-data/pgdata \ |
| 65 | + && chown -R postgres:postgres /postgresus-data |
81 | 66 |
|
82 | 67 | WORKDIR /app |
83 | 68 |
|
84 | | -# Copy Goose from build stage |
85 | | -COPY --from=backend-build /usr/local/bin/goose /usr/local/bin/goose |
86 | | - |
87 | | -# Copy app binary |
| 69 | +# Copy goose and app binary from build stage |
| 70 | +COPY --from=backend-build /go/bin/goose /usr/local/bin/goose |
88 | 71 | COPY --from=backend-build /app/main . |
89 | | - |
90 | | -# Copy migrations directory |
91 | | -COPY backend/migrations ./migrations |
92 | | - |
93 | | -# Copy UI files |
94 | 72 | COPY --from=backend-build /app/ui/build ./ui/build |
| 73 | +COPY --from=backend-build /app/swagger ./swagger |
| 74 | +COPY backend/migrations ./migrations |
95 | 75 |
|
96 | | -# Copy .env file (with fallback to .env.production.example) |
| 76 | +# Copy env file if present |
97 | 77 | COPY backend/.env* /app/ |
98 | | -RUN if [ ! -f /app/.env ]; then \ |
99 | | - if [ -f /app/.env.production.example ]; then \ |
100 | | - cp /app/.env.production.example /app/.env; \ |
101 | | - fi; \ |
| 78 | +RUN if [ ! -f /app/.env ] && [ -f /app/.env.production.example ]; then \ |
| 79 | + cp /app/.env.production.example /app/.env; \ |
102 | 80 | fi |
103 | 81 |
|
104 | | -# Create startup script |
105 | | -COPY <<EOF /app/start.sh |
| 82 | +# Startup script (no rogue \q, DSN format for goose) |
| 83 | +COPY <<'EOF' /app/start.sh |
106 | 84 | #!/bin/bash |
107 | 85 | set -e |
108 | 86 |
|
109 | | -# PostgreSQL 17 binary paths |
110 | 87 | PG_BIN="/usr/lib/postgresql/17/bin" |
111 | 88 |
|
112 | | -# Ensure proper ownership of data directory |
113 | 89 | echo "Setting up data directory permissions..." |
114 | 90 | mkdir -p /postgresus-data/pgdata |
115 | 91 | chown -R postgres:postgres /postgresus-data |
116 | 92 |
|
117 | | -# Initialize PostgreSQL if not already initialized |
118 | 93 | if [ ! -s "/postgresus-data/pgdata/PG_VERSION" ]; then |
119 | | - echo "Initializing PostgreSQL database..." |
120 | | - gosu postgres \$PG_BIN/initdb -D /postgresus-data/pgdata --encoding=UTF8 --locale=C.UTF-8 |
121 | | - |
122 | | - # Configure PostgreSQL |
123 | | - echo "host all all 127.0.0.1/32 md5" >> /postgresus-data/pgdata/pg_hba.conf |
124 | | - echo "local all all trust" >> /postgresus-data/pgdata/pg_hba.conf |
125 | | - echo "port = 5437" >> /postgresus-data/pgdata/postgresql.conf |
126 | | - echo "listen_addresses = 'localhost'" >> /postgresus-data/pgdata/postgresql.conf |
127 | | - echo "shared_buffers = 256MB" >> /postgresus-data/pgdata/postgresql.conf |
128 | | - echo "max_connections = 100" >> /postgresus-data/pgdata/postgresql.conf |
| 94 | + echo "Initializing PostgreSQL database..." |
| 95 | + gosu postgres $PG_BIN/initdb -D /postgresus-data/pgdata --encoding=UTF8 --locale=C.UTF-8 |
| 96 | + echo "host all all 127.0.0.1/32 md5" >> /postgresus-data/pgdata/pg_hba.conf |
| 97 | + echo "local all all trust" >> /postgresus-data/pgdata/pg_hba.conf |
| 98 | + echo "port = 5437" >> /postgresus-data/pgdata/postgresql.conf |
| 99 | + echo "listen_addresses = 'localhost'" >> /postgresus-data/pgdata/postgresql.conf |
| 100 | + echo "shared_buffers = 256MB" >> /postgresus-data/pgdata/postgresql.conf |
| 101 | + echo "max_connections = 100" >> /postgresus-data/pgdata/postgresql.conf |
129 | 102 | fi |
130 | 103 |
|
131 | | -# Start PostgreSQL in background |
132 | 104 | echo "Starting PostgreSQL..." |
133 | | -gosu postgres \$PG_BIN/postgres -D /postgresus-data/pgdata -p 5437 & |
134 | | -POSTGRES_PID=\$! |
| 105 | +gosu postgres $PG_BIN/postgres -D /postgresus-data/pgdata -p 5437 & |
| 106 | +POSTGRES_PID=$! |
135 | 107 |
|
136 | | -# Wait for PostgreSQL to be ready |
137 | 108 | echo "Waiting for PostgreSQL to be ready..." |
138 | 109 | for i in {1..30}; do |
139 | | - if gosu postgres \$PG_BIN/pg_isready -p 5437 -h localhost >/dev/null 2>&1; then |
140 | | - echo "PostgreSQL is ready!" |
141 | | - break |
142 | | - fi |
143 | | - if [ \$i -eq 30 ]; then |
144 | | - echo "PostgreSQL failed to start" |
145 | | - exit 1 |
146 | | - fi |
147 | | - sleep 1 |
| 110 | + if gosu postgres $PG_BIN/pg_isready -p 5437 -h localhost >/dev/null 2>&1; then |
| 111 | + echo "PostgreSQL is ready!" |
| 112 | + break |
| 113 | + fi |
| 114 | + if [ $i -eq 30 ]; then |
| 115 | + echo "PostgreSQL failed to start" |
| 116 | + exit 1 |
| 117 | + fi |
| 118 | + sleep 1 |
148 | 119 | done |
149 | 120 |
|
150 | | -# Create database and set password for postgres user |
151 | 121 | echo "Setting up database and user..." |
152 | | -gosu postgres \$PG_BIN/psql -p 5437 -h localhost -d postgres << 'SQL' |
| 122 | +gosu postgres $PG_BIN/psql -p 5437 -h localhost -d postgres <<'SQL' |
153 | 123 | ALTER USER postgres WITH PASSWORD 'Q1234567'; |
154 | | -CREATE DATABASE "postgresus" OWNER postgres; |
155 | | -\q |
156 | 124 | SQL |
157 | 125 |
|
158 | | -# Start the main application |
| 126 | +# Create the database using createdb (avoids running CREATE DATABASE inside a function) |
| 127 | +if ! gosu postgres $PG_BIN/psql -p 5437 -h localhost -tAc "SELECT 1 FROM pg_database WHERE datname='postgresus'" | grep -q 1; then |
| 128 | + echo "Creating database 'postgresus'..." |
| 129 | + gosu postgres $PG_BIN/createdb -p 5437 -h localhost -O postgres postgresus || { |
| 130 | + echo "Failed to create database 'postgresus'" |
| 131 | + exit 1 |
| 132 | + } |
| 133 | +else |
| 134 | + echo "Database 'postgresus' already exists" |
| 135 | +fi |
| 136 | + |
| 137 | +echo "Running database migrations..." |
| 138 | +# Use goose with explicit driver and DB string; also export env vars so goose can pick them up if it expects |
| 139 | +export GOOSE_DRIVER=postgres |
| 140 | +export GOOSE_DBSTRING="postgres://postgres:Q1234567@localhost:5437/postgresus?sslmode=disable" |
| 141 | +# Run goose with env vars set (goose recognizes GOOSE_DRIVER and GOOSE_DBSTRING) |
| 142 | +/usr/local/bin/goose -dir ./migrations up |
| 143 | + |
159 | 144 | echo "Starting Postgresus application..." |
160 | 145 | exec ./main |
161 | 146 | EOF |
162 | 147 |
|
163 | 148 | RUN chmod +x /app/start.sh |
164 | 149 |
|
165 | 150 | EXPOSE 4005 |
166 | | - |
167 | | -# Volume for PostgreSQL data |
168 | 151 | VOLUME ["/postgresus-data"] |
169 | 152 |
|
170 | | -ENTRYPOINT ["/app/start.sh"] |
171 | | -CMD [] |
| 153 | +CMD ["/app/start.sh"] |
0 commit comments