From a758244666c83be7e58ce916ba1fcfca8e0946d2 Mon Sep 17 00:00:00 2001 From: Adeoye Adefemi Date: Sun, 22 Sep 2024 00:24:37 +0100 Subject: [PATCH 1/4] refactor: sort deps --- Cargo.toml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9301272b..72a52499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,19 +5,24 @@ authors = ["ndelvalle "] edition = "2021" [dependencies] +async-trait = "0.1.81" +axum = { version = "0.7.5" } +axum-extra = { version = "0.9.3", features = ["typed-header"] } +bcrypt = "0.15.1" +# Investigate if wither::bson can be used instead and activate this feature. +bson = { version = "2.10.0", features = ["serde_with", "chrono-0_4"] } +bytes = "1.7.2" +chrono = "0.4.38" config = "0.14.0" +futures = "0.3.30" +jsonwebtoken = "9.3.0" +mime = "0.3.17" +once_cell = "1.20.0" serde = { version = "1.0.204", features = ["derive"] } -serde_json = "1.0.120" serde_derive = "1.0.152" -# Wait for wither to relase a new version. -# https://github.com/thedodd/wither/pull/89#issuecomment-1023644443 -wither = { git = "https://github.com/thedodd/wither", rev = "52fd503" } -futures = "0.3.30" +serde_json = "1.0.120" thiserror = "1.0.63" -axum = { version = "0.7.5" } tokio = { version = "1.39.1", features = ["full"] } -tracing = "0.1.40" -tracing-subscriber = "0.3.18" tower-http = { version = "0.6", features = [ "trace", "compression-br", @@ -25,19 +30,14 @@ tower-http = { version = "0.6", features = [ "sensitive-headers", "cors", ] } -chrono = "0.4.38" -async-trait = "0.1.81" -# Investigate if wither::bson can be used instead and activate this feature. -bson = { version = "2.10.0", features = ["serde_with", "chrono-0_4"] } -jsonwebtoken = "9.3.0" -once_cell = "1.20.0" -bcrypt = "0.15.1" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" validator = { version = "0.18.1", features = ["derive"] } -mime = "0.3.17" -bytes = "1.7.2" -axum-extra = { version = "0.9.3", features = ["typed-header"] } +# Wait for wither to relase a new version. +# https://github.com/thedodd/wither/pull/89#issuecomment-1023644443 +wither = { git = "https://github.com/thedodd/wither", rev = "52fd503" } [dev-dependencies] assert-json-diff = "2.0.2" -reqwest = { version = "0.12.4", features = ["json"] } pretty_assertions = "1.4.1" +reqwest = { version = "0.12.4", features = ["json"] } From a75c17635c9c6e0ddbfe2f373676fe9fba02a3a0 Mon Sep 17 00:00:00 2001 From: Adeoye Adefemi Date: Tue, 24 Sep 2024 15:37:19 +0100 Subject: [PATCH 2/4] chore: add docker --- .dockerignore | 32 +++++++++++++++++++++++++ Dockerfile | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ compose.yaml | 38 ++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..fff0f039 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,32 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +**/.DS_Store +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/secrets.dev.yaml +**/values.dev.yaml +/bin +/target +LICENSE +README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..5a3b6c37 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,65 @@ +# syntax=docker/dockerfile:1 + +ARG RUST_VERSION=1.79.0 +ARG APP_NAME=rustapi + +################################################################################ +# Create a stage for building the application. + +FROM rust:${RUST_VERSION}-alpine AS build + +ARG APP_NAME + +# Adding necessary packages +RUN apk update +RUN apk add pkgconfig openssl openssl-dev musl-dev + +# Build the application. +RUN rustup target add x86_64-unknown-linux-musl + +# copy the source +WORKDIR /app +COPY . . + +RUN cargo build --target=aarch64-unknown-linux-musl --release + +# RUN strip ./target/release/aarch64-unknown-linux-musl/$APP_NAME + +# RUN cp ./target/release/aarch64-unknown-linux-musl/$APP_NAME /bin/server + +################################################################################ +# Create a new stage for running the application that contains the minimal +# runtime dependencies for the application. This often uses a different base +# image from the build stage where the necessary files are copied from the build +# stage. +# +# The example below uses the alpine image as the foundation for running the app. +# By specifying the "3.18" tag, it will use version 3.18 of alpine. If +# reproducability is important, consider using a digest +# (e.g., alpine@sha256:664888ac9cfd28068e062c991ebcff4b4c7307dc8dd4df9e728bedde5c449d91). + +FROM alpine:latest AS final + +WORKDIR /app +RUN cd /app +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/go/dockerfile-user-best-practices/ +ARG UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + appuser +USER appuser + +# Copy the executable from the "build" stage. +COPY --from=build /app/target/release/$APP_NAME /bin/server + +# Expose the port that the application listens on. +EXPOSE 3000 + +# What the container should run when it is started. +CMD ["/bin/server"] diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 00000000..9c4c15af --- /dev/null +++ b/compose.yaml @@ -0,0 +1,38 @@ +version: "3" + +services: + app: + build: + context: . + target: final + ports: + - 3000:3000 + environment: + - PORT=3000 + - DB_CONNECTION_URL = postgres://rustapi:RAa6dHNblVoJboG6fyFlbCvlYe7@database + + depends_on: + database: + condition: service_started + # the DB + database: + image: postgres:15-alpine + restart: always + shm_size: 100mb + volumes: + - db-data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=rustapi.db + - POSTGRES_USER=rustapi + - POSTGRES_PASSWORD=RAa6dHNblVoJboG6fyFlbCvlYe7 + expose: + - 5432 + healthcheck: + test: [ "CMD", "pg_isready -d rustapi.db rustapi"] + interval: 10s + timeout: 5s + retries: 5 +volumes: + db-data: + + From 4b2e7c3f966bb45832d8f106eacc0439d9e2757d Mon Sep 17 00:00:00 2001 From: Adeoye Adefemi Date: Tue, 24 Sep 2024 15:37:43 +0100 Subject: [PATCH 3/4] refactor --- Cargo.toml | 4 ++++ src/main.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 72a52499..e9dfde4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" authors = ["ndelvalle "] edition = "2021" +[[bin]] +name ="rustapi" +path ="./src/main.rs" + [dependencies] async-trait = "0.1.81" axum = { version = "0.7.5" } diff --git a/src/main.rs b/src/main.rs index 5e32fb2b..7c8738cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::net::SocketAddr; +use std::net::{Ipv4Addr, SocketAddrV4}; use tokio::net::TcpListener; use tracing::info; @@ -25,7 +25,7 @@ use settings::SETTINGS; #[tokio::main] async fn main() -> Result<(), std::io::Error> { let port = SETTINGS.server.port; - let address = SocketAddr::from(([127, 0, 0, 1], port)); + let address = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port); let app = app::create_app().await; From c47e0ac588a670373446dc1da771d16a2148cd0f Mon Sep 17 00:00:00 2001 From: Adeoye Adefemi Date: Tue, 24 Sep 2024 16:12:21 +0100 Subject: [PATCH 4/4] refactor --- Dockerfile | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5a3b6c37..be271660 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,11 @@ # syntax=docker/dockerfile:1 +# Comments are provided throughout this file to help you get started. +# If you need more help, visit the Dockerfile reference guide at +# https://docs.docker.com/go/dockerfile-reference/ + +# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 + ARG RUST_VERSION=1.79.0 ARG APP_NAME=rustapi @@ -7,25 +13,28 @@ ARG APP_NAME=rustapi # Create a stage for building the application. FROM rust:${RUST_VERSION}-alpine AS build - ARG APP_NAME - -# Adding necessary packages -RUN apk update -RUN apk add pkgconfig openssl openssl-dev musl-dev - -# Build the application. -RUN rustup target add x86_64-unknown-linux-musl - -# copy the source WORKDIR /app -COPY . . - -RUN cargo build --target=aarch64-unknown-linux-musl --release -# RUN strip ./target/release/aarch64-unknown-linux-musl/$APP_NAME +# Install host build dependencies. +RUN apk add --no-cache clang lld musl-dev git -# RUN cp ./target/release/aarch64-unknown-linux-musl/$APP_NAME /bin/server +# Build the application. +# Leverage a cache mount to /usr/local/cargo/registry/ +# for downloaded dependencies, a cache mount to /usr/local/cargo/git/db +# for git repository dependencies, and a cache mount to /app/target/ for +# compiled dependencies which will speed up subsequent builds. +# Leverage a bind mount to the src directory to avoid having to copy the +# source code into the container. Once built, copy the executable to an +# output directory before the cache mounted /app/target is unmounted. +RUN --mount=type=bind,source=src,target=src \ + --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ + --mount=type=cache,target=/app/target/ \ + --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/usr/local/cargo/registry/ \ +cargo build --locked --release && \ +cp ./target/release/$APP_NAME /bin/server ################################################################################ # Create a new stage for running the application that contains the minimal @@ -37,11 +46,8 @@ RUN cargo build --target=aarch64-unknown-linux-musl --release # By specifying the "3.18" tag, it will use version 3.18 of alpine. If # reproducability is important, consider using a digest # (e.g., alpine@sha256:664888ac9cfd28068e062c991ebcff4b4c7307dc8dd4df9e728bedde5c449d91). +FROM alpine:3.18 AS final -FROM alpine:latest AS final - -WORKDIR /app -RUN cd /app # Create a non-privileged user that the app will run under. # See https://docs.docker.com/go/dockerfile-user-best-practices/ ARG UID=10001 @@ -56,7 +62,7 @@ RUN adduser \ USER appuser # Copy the executable from the "build" stage. -COPY --from=build /app/target/release/$APP_NAME /bin/server +COPY --from=build /bin/server /bin/ # Expose the port that the application listens on. EXPOSE 3000