diff --git a/.dockerignore b/.dockerignore index 94eed16..128f7c1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -25,4 +25,6 @@ fly.toml **/*.rs.bk .cargo/ *.wasm -*.wasm.map \ No newline at end of file +*.wasm.map +.gitignore +.git \ No newline at end of file diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..d4ecb2c --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,71 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + - dev + tags: + - 'v*' + pull_request: + branches: + - main + workflow_dispatch: # Allows manual trigger + +env: + DOCKER_IMAGE: ${{secrets.DOCKER_USERNAME}}/rust-nigeria-website + +jobs: + build-and-push: + runs-on: ubuntu-latest + environment: test + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.DOCKER_IMAGE }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: | + type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache + type=registry,ref=${{ env.DOCKER_IMAGE }}:latest + cache-to: type=registry,ref=${{ env.DOCKER_IMAGE }}:buildcache,mode=max + platforms: linux/amd64 + build-args: | + BUILDKIT_INLINE_CACHE=1 + + - name: Image digest + run: echo ${{ steps.meta.outputs.digest }} + + - name: Trigger Render Deploy + run: curl -f "$RENDER_HOOK" || exit 1 + env: + RENDER_HOOK: ${{ secrets.RENDER_HOOK }} diff --git a/Dockerfile b/Dockerfile index 3c752fd..be66a80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,70 +1,87 @@ -# Chef stage for preparing recipe ---- -FROM rustlang/rust:nightly-alpine AS chef - -RUN apk update && \ - apk add --no-cache musl-dev - -RUN cargo install cargo-chef +FROM rust:1.92.0-alpine3.23 AS base + +RUN apk add --no-cache \ + bash \ + curl \ + git \ + npm \ + build-base \ + openssl-dev \ + pkgconf \ + libc-dev \ + musl-dev \ + binaryen \ + perl \ + python3 \ + cmake + +COPY rust-toolchain.toml ./ +RUN rustup show +# Install all Rust tools once in base +RUN cargo install cargo-binstall +RUN cargo install cargo-chef +RUN npm install -g sass +RUN cargo install stylance-cli +RUN cargo binstall cargo-leptos -y +RUN cargo install -f wasm-bindgen-cli --version 0.2.105 +RUN rustup target add wasm32-unknown-unknown WORKDIR /work - ###### Planner stage #### -FROM chef AS planner +FROM base AS planner -# Only copy files needed for cargo-chef to analyze dependencies -COPY Cargo.toml Cargo.lock ./ -COPY src ./src +# Only copy dependency files, NOT source code +COPY . . RUN cargo chef prepare --recipe-path recipe.json +###### Chef stage - cook dependencies #### +FROM base AS chef -###### Builder stage ###### -FROM chef AS builder - -# Install system dependencies -RUN apk update && \ - apk add --no-cache bash curl npm libc-dev git - -# Install SASS (used by stylance output) -RUN npm install -g sass - -# Install Rust tools -RUN cargo install stylance-cli -RUN curl --proto '=https' --tlsv1.2 -LsSf https://github.com/leptos-rs/cargo-leptos/releases/download/v0.3.0/cargo-leptos-installer.sh | sh - -RUN cargo install -f wasm-bindgen-cli --version 0.2.105 -# Add the WASM target -RUN rustup target add wasm32-unknown-unknown +COPY --from=planner /work/recipe.json recipe.json +RUN cargo chef cook --release --recipe-path recipe.json +###### Builder stage ###### +FROM base AS builder WORKDIR /work -# Copy recipe and cook dependencies (this layer gets cached) -COPY --from=planner /work/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json +# Copy cooked dependencies +COPY --from=chef /work/target target +COPY --from=chef /usr/local/cargo /usr/local/cargo -# Now copy the actual source code +# Now copy source code COPY . . -# Run stylance first +# Run stylance and build RUN stylance . - RUN cargo leptos build --release -vv - ##### Production runner ##### -FROM rustlang/rust:nightly-alpine AS runner +FROM debian:bookworm-slim AS runner WORKDIR /app +# Install runtime dependencies +RUN apt-get update -y \ + && apt-get install -y --no-install-recommends openssl ca-certificates \ + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +# Copy only what's needed for runtime COPY --from=builder /work/data /app/data COPY --from=builder /work/target/release/rust-nigeria-website /app/ COPY --from=builder /work/target/site /app/site COPY --from=builder /work/Cargo.toml /app/ + + + ENV RUST_LOG="debug" ENV LEPTOS_SITE_ADDR="0.0.0.0:8080" ENV LEPTOS_SITE_ROOT=./site + EXPOSE 8080 -CMD ["/app/rust-nigeria-website"] \ No newline at end of file +CMD ["/app/rust-nigeria-website"] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fc8ca8c..b98b0be 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly" +channel = "nightly-2025-12-22" targets = ["wasm32-unknown-unknown"]