diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..5f73ba4 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,53 @@ +name: Build and Deploy Docker to GHCR + +# This workflow runs when any of the following occur: +# - A push is made to a branch called `main` +# - A tag starting with "v" is created +on: + push: + branches: + - main + tags: + - v* +env: + IMAGE_NAME: stoic_quotes +# +jobs: + # This pushes the image to GitHub Packages. + push: + runs-on: ubuntu-latest + + permissions: + packages: write + contents: read + + steps: + - uses: actions/checkout@v4 + + - name: Build image + run: docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}" + + - name: Log in to registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin + + - name: Push image + run: | + IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME + + # This changes all uppercase characters to lowercase. + IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + + # This strips the git ref prefix from the version. + VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + + # This strips the "v" prefix from the tag name. + [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') + + # This uses the Docker `latest` tag convention. + [ "$VERSION" == "main" ] && VERSION=latest + + echo IMAGE_ID=$IMAGE_ID + echo VERSION=$VERSION + docker tag $IMAGE_NAME $IMAGE_ID:$VERSION + docker push $IMAGE_ID:$VERSION + diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..d38c5d2 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,29 @@ +name: Build and Test Docker Image + +on: + push: + branches: + - main + pull_request: {} + workflow_dispatch: null + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t stoic_quotes . + + - name: Run Docker + run: docker run -d --name stoic_quotes -p 3000:3000 stoic_quotes + + - name: Display Docker container logs + run: docker logs stoic_quotes + + - name: Test Docker + run: curl --fail localhost:3000/ || exit 1 + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..26275e7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,48 @@ +# Start from the official Rust image +FROM rust:latest as builder + +# Install musl-tools +RUN apt-get update && apt-get install -y musl-tools && rm -rf /var/lib/apt/lists/* + +# Target the musl architecture for a fully static binary +RUN rustup target add x86_64-unknown-linux-musl + +# Set the working directory +WORKDIR /usr/src/app + +# Add labels for OCI annotations +LABEL org.opencontainers.image.source="https://github.com/storopoli/stoic-quotes" \ + org.opencontainers.image.description="Stoic Quotes" \ + org.opencontainers.image.licenses="MIT" + +# Copy project's Cargo.toml file +COPY ./Cargo.toml ./ + +# This dummy build is to cache dependencies so they don't need to be rebuilt +# every time your source changes +RUN mkdir src/ && \ + echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs && \ + cargo build --release --target x86_64-unknown-linux-musl && \ + rm -f target/x86_64-unknown-linux-musl/release/deps/stoic* + +# Copy project's source code and other relevant folders to the Docker image +COPY ./src ./src +COPY ./assets ./assets +COPY ./data ./data +COPY ./templates ./templates + +# Build application for release target musl +RUN cargo build --release --target x86_64-unknown-linux-musl + +# Start a new stage from a slim version of Debian to reduce the size of the final image +FROM debian:buster-slim + +# Copy the binary from the builder stage to the new stage +COPY --from=builder /usr/src/app/target/x86_64-unknown-linux-musl/release/stoic-quotes /usr/local/bin/stoic-quotes + +# Expose port 3000 +EXPOSE 3000 + +# Command to run the binary +CMD ["stoic-quotes"] + diff --git a/README.md b/README.md index 5a593a8..2b53eb7 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,19 @@ $ curl stoicquotes.io - Seneca ``` +## Docker + +You can also deploy it using Docker from the GitHub Container Registry: + +```bash +docker pull ghcr.io/storopoli/stoic_quotes:latest + +docker run -d --name stoic_quotes -p 443:3000 stoic_quotes +``` + +By default it exposes port 3000 on the `axum` server. +You can safely map to HTTP (port 80) or HTTPS (port 443). + ## License This content is licensed under a