Skip to content

Commit 28bbc05

Browse files
committed
chore: docker setup
1 parent 29fdb0c commit 28bbc05

5 files changed

Lines changed: 271 additions & 0 deletions

File tree

.dockerignore

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Git files
2+
.git/
3+
.gitignore
4+
.github/
5+
6+
# Documentation
7+
*.md
8+
LICENSE
9+
docs/
10+
11+
# Development files
12+
.vscode/
13+
.idea/
14+
*.swp
15+
*.swo
16+
*~
17+
18+
# Build artifacts (we'll build fresh in Docker)
19+
target/
20+
dist/
21+
build/
22+
23+
# Database files
24+
*.db
25+
*.db-shm
26+
*.db-wal
27+
flashy.db*
28+
29+
# Environment files
30+
.env
31+
.env.*
32+
33+
# Node modules (will be installed in Docker)
34+
node_modules/
35+
36+
# SQLx offline data (generated during Docker build)
37+
.sqlx/
38+
39+
# Test files
40+
tests/
41+
end2end/
42+
*.test.js
43+
44+
# CI/CD artifacts
45+
artifacts/
46+
47+
# OS files
48+
.DS_Store
49+
Thumbs.db
50+
51+
# Logs
52+
*.log
53+
logs/
54+
55+
# Temporary files
56+
tmp/
57+
temp/
58+
*.tmp
59+
60+
# Other project directories
61+
rustify-app/
62+
genanki-rs/

Dockerfile

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# =============================================================================
2+
# Stage 1: Tool Cache - Build/install cargo tools once and cache them
3+
# =============================================================================
4+
FROM rustlang/rust:nightly-alpine AS tool-cache
5+
6+
RUN apk add --no-cache libc-dev openssl-dev sqlite-dev perl make
7+
8+
# Install cargo tools in a dedicated stage for better caching
9+
RUN cargo install sqlx-cli --no-default-features --features sqlite --locked
10+
RUN cargo install cargo-leptos --locked
11+
12+
# =============================================================================
13+
# Stage 2: Builder - Build the Leptos SSR application
14+
# =============================================================================
15+
FROM rustlang/rust:nightly-alpine AS builder
16+
17+
# Install build dependencies
18+
RUN apk update && \
19+
apk add --no-cache \
20+
bash \
21+
curl \
22+
npm \
23+
libc-dev \
24+
binaryen \
25+
openssl-dev \
26+
openssl-libs-static \
27+
pkgconfig \
28+
sqlite \
29+
sqlite-dev \
30+
musl-dev
31+
32+
# Copy pre-built tools from cache stage
33+
COPY --from=tool-cache /usr/local/cargo/bin/sqlx /usr/local/cargo/bin/sqlx
34+
COPY --from=tool-cache /usr/local/cargo/bin/cargo-sqlx /usr/local/cargo/bin/cargo-sqlx
35+
COPY --from=tool-cache /usr/local/cargo/bin/cargo-leptos /usr/local/cargo/bin/cargo-leptos
36+
37+
# Add WASM target for client-side hydration
38+
RUN rustup target add wasm32-unknown-unknown
39+
40+
# Set working directory
41+
WORKDIR /work
42+
43+
# Copy dependency manifests first and create dummy src for dependency caching
44+
COPY Cargo.toml Cargo.lock ./
45+
RUN mkdir -p src && \
46+
echo "fn main() {}" > src/main.rs && \
47+
echo "pub fn dummy() {}" > src/lib.rs
48+
RUN cargo build --release --features ssr && rm -rf src target/release/deps/flashy*
49+
50+
# Now copy real source code
51+
COPY src ./src
52+
COPY style ./style
53+
COPY public ./public
54+
COPY migrations ./migrations
55+
56+
ENV DATABASE_URL=sqlite:build.db
57+
RUN sqlx database create && \
58+
sqlx migrate run && \
59+
cargo sqlx prepare --workspace -- --lib --features ssr && \
60+
rm build.db*
61+
62+
# Set SQLx to offline mode for the actual build
63+
ENV SQLX_OFFLINE=true
64+
65+
# Build the application in release mode with optimizations
66+
ENV CARGO_PROFILE_RELEASE_STRIP=symbols
67+
ENV CARGO_PROFILE_RELEASE_LTO=true
68+
ENV CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1
69+
RUN cargo leptos build --release -vv
70+
71+
# =============================================================================
72+
# Stage 3: Runtime Dependencies - Build minimal sqlx for runtime
73+
# =============================================================================
74+
FROM rustlang/rust:nightly-alpine AS runtime-tools
75+
76+
RUN apk add --no-cache libc-dev openssl-dev sqlite-dev musl-dev
77+
78+
# Build sqlx statically for distroless
79+
RUN cargo install sqlx-cli --no-default-features --features sqlite --locked \
80+
--target x86_64-unknown-linux-musl || \
81+
cargo install sqlx-cli --no-default-features --features sqlite --locked
82+
83+
# =============================================================================
84+
# Stage 4: Runner - Distroless minimal runtime image
85+
# =============================================================================
86+
# :debug needed for busybox shell for entrypoint script
87+
FROM gcr.io/distroless/cc-debian12:debug
88+
89+
WORKDIR /app
90+
91+
COPY --from=builder --chmod=755 /work/target/release/flashy /app/flashy
92+
COPY --from=builder --chmod=644 /work/Cargo.toml /app/Cargo.toml
93+
94+
COPY --from=builder /work/target/site /app/site
95+
COPY --from=builder /work/migrations /app/migrations
96+
97+
COPY --from=runtime-tools --chmod=755 /usr/local/cargo/bin/sqlx /app/sqlx
98+
99+
COPY --chmod=755 docker-entrypoint.sh /app/docker-entrypoint.sh
100+
101+
ENV RUST_LOG="info"
102+
ENV LEPTOS_SITE_ADDR="0.0.0.0:8080"
103+
ENV LEPTOS_SITE_ROOT="/app/site"
104+
ENV DATABASE_URL="sqlite:/app/data/flashy.db"
105+
106+
EXPOSE 8080
107+
108+
VOLUME ["/app/data"]
109+
110+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
111+
CMD ["/busybox/wget", "-q", "-O", "/dev/null", "http://localhost:8080/"]
112+
113+
ENTRYPOINT ["/busybox/sh", "/app/docker-entrypoint.sh"]

docker-compose-dev.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
services:
2+
minio:
3+
image: minio/minio:latest
4+
command: server /data --console-address ":9001"
5+
ports:
6+
- "9000:9000"
7+
- "9001:9001"
8+
environment:
9+
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
10+
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
11+
volumes:
12+
- minio_data:/data
13+
14+
volumes:
15+
minio_data:

docker-compose.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,37 @@
11
services:
2+
flashy:
3+
container_name: flashy
4+
image: ghcr.io/404simon/flashy:latest
5+
# Run as host user to avoid permission issues with bind-mounted volumes
6+
# Set UID/GID in .env file or they default to 1000:1000
7+
user: "${UID:-1000}:${GID:-1000}"
8+
ports:
9+
- "8080:8080"
10+
volumes:
11+
- ./data:/app/data
12+
environment:
13+
- DATABASE_URL=sqlite:/app/data/flashy.db
14+
- RUST_LOG=info
15+
- LEPTOS_SITE_ADDR=0.0.0.0:8080
16+
- LEPTOS_SITE_ROOT=/app/site
17+
restart: unless-stopped
18+
# Security hardening
19+
security_opt:
20+
- no-new-privileges:true
21+
cap_drop:
22+
- ALL
23+
read_only: true
24+
tmpfs:
25+
- /tmp
26+
healthcheck:
27+
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/"]
28+
interval: 30s
29+
timeout: 3s
30+
start_period: 5s
31+
retries: 3
32+
depends_on:
33+
- minio
34+
235
minio:
336
image: minio/minio:latest
437
command: server /data --console-address ":9001"
@@ -10,6 +43,7 @@ services:
1043
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
1144
volumes:
1245
- minio_data:/data
46+
restart: unless-stopped
1347

1448
volumes:
1549
minio_data:

docker-entrypoint.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/busybox/sh
2+
set -e
3+
4+
DB_URL="${DATABASE_URL:-sqlite:/app/data/flashy.db}"
5+
DB_PATH=$(echo "$DB_URL" | sed 's|^sqlite:||')
6+
DB_DIR=$(dirname "$DB_PATH")
7+
8+
if ! mkdir -p "$DB_DIR" 2>/dev/null; then
9+
echo "ERROR: Cannot create data directory: $DB_DIR"
10+
echo "Please ensure the volume is mounted with proper permissions"
11+
exit 1
12+
fi
13+
14+
if [ -f "$DB_PATH" ]; then
15+
echo "Database file found - will run migrations to ensure schema is up-to-date"
16+
DB_EXISTS=true
17+
else
18+
echo "Database file not found - will create new database and run initial migrations"
19+
DB_EXISTS=false
20+
fi
21+
22+
echo "========================================="
23+
echo "Running database setup..."
24+
echo "========================================="
25+
26+
cd /app
27+
28+
if [ "$DB_EXISTS" = false ]; then
29+
echo "Creating new database..."
30+
/app/sqlx database create
31+
echo "Database created successfully"
32+
33+
echo "Running initial migrations..."
34+
/app/sqlx migrate run
35+
echo "Initial migrations completed"
36+
else
37+
echo "Database already exists, checking for new migrations..."
38+
/app/sqlx migrate run
39+
echo "Migrations up to date"
40+
fi
41+
42+
echo "========================================="
43+
echo "Starting Flashy application..."
44+
echo "========================================="
45+
46+
# Execute the application (replaces this shell process)
47+
exec /app/flashy

0 commit comments

Comments
 (0)