From bfba0c97cb9a8465595201c925503be4729f4134 Mon Sep 17 00:00:00 2001 From: Rohit Sachdeva Date: Wed, 9 Oct 2024 19:14:02 -0500 Subject: [PATCH] Add Docker for Server-Based gRPC and REST gateway --- .cargo/config.toml | 2 + .dockerignore | 34 ++++++++ .gitignore | 2 + Cargo.lock | 20 ++--- Dockerfile.for.compose.grpc | 83 +++++++++++++++++++ Dockerfile.for.compose.rest.gateway | 80 ++++++++++++++++++ README.md | 22 +++-- compose.grpc.yaml | 18 ++++ compose.rest.yaml | 14 ++++ drive-deposits-cal-types/Cargo.toml | 2 +- drive-deposits-check-cmd/Cargo.toml | 2 +- drive-deposits-event-source/Cargo.toml | 2 +- drive-deposits-event-source/src/eb.rs | 4 +- drive-deposits-grpc-server/Cargo.toml | 2 +- drive-deposits-grpc-server/src/main.rs | 4 +- drive-deposits-lambda-db-types/Cargo.toml | 2 +- .../Cargo.toml | 2 +- drive-deposits-logs-lambda-target/Cargo.toml | 2 +- drive-deposits-proto-grpc-types/Cargo.toml | 2 +- drive-deposits-rest-gateway-server/Cargo.toml | 2 +- .../src/drive_deposits_client.rs | 7 +- drive-deposits-rest-types/Cargo.toml | 2 +- justfile | 30 +++++++ 23 files changed, 311 insertions(+), 29 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile.for.compose.grpc create mode 100644 Dockerfile.for.compose.rest.gateway create mode 100644 compose.grpc.yaml create mode 100644 compose.rest.yaml diff --git a/.cargo/config.toml b/.cargo/config.toml index de50370..d1504e4 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,8 @@ RUST_LOG = { value = "drive_deposits_rest_types=debug,drive_deposits_proto_grpc_types=debug,drive_deposits_event_source=debug,drive_deposits_lambda_db_types=debug,drive_deposits_logs_lambda_target=debug,by_level_lambda_writer=debug,drive_deposits_lambda_dynamodb_reader=debug,by_level_lambda_reader=debug,drive_deposits_cal_types=debug,drive_deposits_check_cmd=debug,drive_deposits_grpc_server=debug,drive_deposits_rest_gateway_server=debug", force = true } +GRPC_SERVER_ADDRESS = "http://[::]:50052" + # default settings -- can be changed by setting these env. variables on command line SEND_CAL_EVENTS = "true" USE_LOCALSTACK = "false" diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6d0f80e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,34 @@ +# 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 +.idea/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/.idea +**/*.iml +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose.y*ml +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/secrets.dev.yaml +**/values.dev.yaml +/bin +/target +LICENSE +README.md diff --git a/.gitignore b/.gitignore index 7be897a..3c5a590 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ target/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb +**/.env + diff --git a/Cargo.lock b/Cargo.lock index 3df8135..1199a20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1098,7 +1098,7 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "drive-deposits-cal-types" -version = "0.30.0" +version = "0.50.0" dependencies = [ "anyhow", "chrono", @@ -1121,7 +1121,7 @@ dependencies = [ [[package]] name = "drive-deposits-check-cmd" -version = "0.30.0" +version = "0.50.0" dependencies = [ "anyhow", "assert_cmd", @@ -1144,7 +1144,7 @@ dependencies = [ [[package]] name = "drive-deposits-event-source" -version = "0.30.0" +version = "0.50.0" dependencies = [ "anyhow", "aws-config", @@ -1162,7 +1162,7 @@ dependencies = [ [[package]] name = "drive-deposits-grpc-server" -version = "0.30.0" +version = "0.50.0" dependencies = [ "drive-deposits-cal-types", "drive-deposits-event-source", @@ -1178,7 +1178,7 @@ dependencies = [ [[package]] name = "drive-deposits-lambda-db-types" -version = "0.30.0" +version = "0.50.0" dependencies = [ "aws-sdk-dynamodb", "drive-deposits-rest-types", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "drive-deposits-lambda-dynamodb-reader" -version = "0.30.0" +version = "0.50.0" dependencies = [ "aws-config", "aws-sdk-dynamodb", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "drive-deposits-logs-lambda-target" -version = "0.30.0" +version = "0.50.0" dependencies = [ "aws-config", "aws-sdk-dynamodb", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "drive-deposits-proto-grpc-types" -version = "0.30.0" +version = "0.50.0" dependencies = [ "drive-deposits-rest-types", "heck", @@ -1238,7 +1238,7 @@ dependencies = [ [[package]] name = "drive-deposits-rest-gateway-server" -version = "0.30.0" +version = "0.50.0" dependencies = [ "axum", "drive-deposits-proto-grpc-types", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "drive-deposits-rest-types" -version = "0.30.0" +version = "0.50.0" dependencies = [ "chrono", "chrono-tz", diff --git a/Dockerfile.for.compose.grpc b/Dockerfile.for.compose.grpc new file mode 100644 index 0000000..d605446 --- /dev/null +++ b/Dockerfile.for.compose.grpc @@ -0,0 +1,83 @@ +# syntax=docker/dockerfile:1 + +ARG RUST_VERSION=1.81.0 +ARG APP_NAME=drive-deposits-grpc-server + +################################################################################ +# Create a stage for building the application. + +FROM rust:${RUST_VERSION}-alpine AS build +ARG APP_NAME +# not used as we are using a bind mount with absolute path +WORKDIR /drive-deposits + +# Install host build dependencies. +RUN apk add --no-cache clang lld musl-dev git + +RUN apk add --no-cache protobuf-dev + + +# Build the application. +# Mounting for caching dependencies and build artifacts +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/tmp/cargo-target \ + --mount=type=bind,source=.,target=/tmp/build \ + set -x && \ + ls -la /drive-deposits && \ + cd /tmp/build && \ + mkdir -p /tmp/cargo-target && \ + CARGO_TARGET_DIR=/tmp/cargo-target cargo build --package $APP_NAME --locked --release && \ + echo "Contents of /tmp/cargo-target/release/ directory:" && \ + ls -la /tmp/cargo-target/release/ && \ + if [ -f /tmp/cargo-target/release/$APP_NAME ]; then \ + mkdir -p /bin/server && \ + cp /tmp/cargo-target/release/$APP_NAME /bin/server/$APP_NAME && \ + echo "Contents of /bin/server directory:" && \ + ls -la /bin/server; \ + else \ + echo "Binary $APP_NAME not found in /tmp/cargo-target/release/"; \ + exit 1; \ + fi + +################################################################################# +# Create a new stage for running the application +# could use distroless +# FROM gcr.io/distroless/cc-debian11 +# or slim +# FROM debian:buster-slim +# this is docker init by default +FROM alpine:3.18 AS final + +WORKDIR /bin + +# 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 + +WORKDIR /bin + +COPY --from=build /bin/server/$APP_NAME . + +RUN echo "Contents of workdir /bin directory for drive-deposits-grpc-server in final:" && \ + ls -la /bin + + +EXPOSE 50052 + +ENV RUST_LOG="drive_deposits_rest_types=debug,drive_deposits_proto_grpc_types=debug,drive_deposits_event_source=debug,drive_deposits_cal_types=debug,drive_deposits_grpc_server=debug" + +ENV SEND_CAL_EVENTS="true" +ENV USE_LOCALSTACK="false" + + +CMD ["/bin/drive-deposits-grpc-server"] diff --git a/Dockerfile.for.compose.rest.gateway b/Dockerfile.for.compose.rest.gateway new file mode 100644 index 0000000..dc2af8e --- /dev/null +++ b/Dockerfile.for.compose.rest.gateway @@ -0,0 +1,80 @@ +# syntax=docker/dockerfile:1 + +ARG RUST_VERSION=1.81.0 +ARG APP_NAME=drive-deposits-rest-gateway-server + +################################################################################ +# Create a stage for building the application. + +FROM rust:${RUST_VERSION}-alpine AS build +ARG APP_NAME +# not used as we are using a bind mount with absolute path +WORKDIR /drive-deposits + +# Install host build dependencies. +RUN apk add --no-cache clang lld musl-dev git + +RUN apk add --no-cache protobuf-dev + + +# Build the application. +# Mounting for caching dependencies and build artifacts +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/tmp/cargo-target \ + --mount=type=bind,source=.,target=/tmp/build \ + set -x && \ + ls -la /drive-deposits && \ + cd /tmp/build && \ + mkdir -p /tmp/cargo-target && \ + CARGO_TARGET_DIR=/tmp/cargo-target cargo build --package $APP_NAME --locked --release && \ + echo "Contents of /tmp/cargo-target/release/ directory:" && \ + ls -la /tmp/cargo-target/release/ && \ + if [ -f /tmp/cargo-target/release/$APP_NAME ]; then \ + mkdir -p /bin/server && \ + cp /tmp/cargo-target/release/$APP_NAME /bin/server/$APP_NAME && \ + echo "Contents of /bin/server directory:" && \ + ls -la /bin/server; \ + else \ + echo "Binary $APP_NAME not found in /tmp/cargo-target/release/"; \ + exit 1; \ + fi + +################################################################################# +# Create a new stage for running the application +# could use distroless +# FROM gcr.io/distroless/cc-debian11 +# or slim +# FROM debian:buster-slim +# this is docker init by default +FROM alpine:3.18 AS final + +WORKDIR /bin + +# 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 + +WORKDIR /bin + +COPY --from=build /bin/server/$APP_NAME . + +RUN echo "Contents of workdir /bin directory for drive-deposits-rest-gateway-server in final:" && \ + ls -la /bin + +EXPOSE 3000 + +ENV RUST_LOG="drive_deposits_rest_types=debug,drive_deposits_proto_grpc_types=debug,drive_deposits_rest_gateway_server=debug" + +ENV GRPC_SERVER_ADDRESS="http://drive-deposits-grpc-server:50052" + +CMD ["/bin/drive-deposits-rest-gateway-server"] diff --git a/README.md b/README.md index 979d0ef..879e303 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - [Synchronous Microservices Components](#synchronous-microservices-components) - [Asynchronous Microservices Components](#asynchronous-microservices-components) - [Bridging Synchronous and Asynchronous Components In DriveDeposits Microservices](#bridging-synchronous-and-asynchronous-components-in-drivedeposits-microservices) -- [Deployment of DriveDeposits Microservices](#deployment-of-drivedeposits-microservices) +- [Deployment of Microservices](#deployment-of-microservices) - [Hybrid Integration Testing Tool](#hybrid-integration-testing-tool) - [Running Tests](#running-tests) - [Integration tests](#integration-tests) @@ -251,7 +251,9 @@ microservices ecosystem. [Back to Table of Contents](#table-of-contents) -### Deployment of DriveDeposits Microservices +### Deployment of Microservices + +- **Serverless**: AWS using SAM This project uses SAM (Serverless Application Model) for deploying the following AWS resources that support our microservices architecture: @@ -293,10 +295,18 @@ related resources. `just deploy-drive-deposits-dynamodb-queries-only` -#### Run server-based microservices (REST gateway and gRPC Servers) +- **Server-based**: + - **Natively** (without Docker) -`just run-drive-deposits-grpc-server` -`just run-drive-deposits-rest-grpc-gateway-server` + `just run-drive-deposits-grpc-server` + + `just run-drive-deposits-rest-grpc-gateway-server` + + - **Docker Compose** + + `just compose-up-grpc-server` + + `just compose-up-rest-server` #### Test microservices integration @@ -444,7 +454,7 @@ Following is convenience so that in development can iterate faster: Should see "Ready." -- There is a Terminal now in Docker Desktop itself so that is a good place to run this command. -#### deploy everything in localstack -- aws deployment related commands for EventBridge, EventBus, Cloudwatch log groups and Lambda target function for writing to DynamoDB and Lambda DynamoDB reader +#### deploy everything serverless in Localstack - aws deployment related commands for EventBridge, EventBus, Cloudwatch log groups and Lambda target function for writing to DynamoDB and Lambda DynamoDB reader `just localstack-deploy-drive-deposits-dynamodb-queries` diff --git a/compose.grpc.yaml b/compose.grpc.yaml new file mode 100644 index 0000000..ee4a0a3 --- /dev/null +++ b/compose.grpc.yaml @@ -0,0 +1,18 @@ +services: + drive-deposits-grpc-server: + build: + context: . + target: final + dockerfile: Dockerfile.for.compose.grpc + ports: + - "50052:50052" + networks: + - drive-deposits-network + environment: + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} + +networks: + drive-deposits-network: + driver: bridge \ No newline at end of file diff --git a/compose.rest.yaml b/compose.rest.yaml new file mode 100644 index 0000000..8576830 --- /dev/null +++ b/compose.rest.yaml @@ -0,0 +1,14 @@ +services: + drive-deposits-rest-gateway-server: + build: + context: . + target: final + dockerfile: Dockerfile.for.compose.rest.gateway + ports: + - "3000:3000" + networks: + - drive-deposits-network + +networks: + drive-deposits-network: + driver: bridge diff --git a/drive-deposits-cal-types/Cargo.toml b/drive-deposits-cal-types/Cargo.toml index dcbdb37..e8f5d99 100644 --- a/drive-deposits-cal-types/Cargo.toml +++ b/drive-deposits-cal-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-cal-types" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-check-cmd/Cargo.toml b/drive-deposits-check-cmd/Cargo.toml index 6d9a8fe..1b764dc 100644 --- a/drive-deposits-check-cmd/Cargo.toml +++ b/drive-deposits-check-cmd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-check-cmd" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-event-source/Cargo.toml b/drive-deposits-event-source/Cargo.toml index 3b520e4..8738565 100644 --- a/drive-deposits-event-source/Cargo.toml +++ b/drive-deposits-event-source/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-event-source" -version = "0.30.0" +version = "0.50.0" edition = "2021" diff --git a/drive-deposits-event-source/src/eb.rs b/drive-deposits-event-source/src/eb.rs index e66b42e..b308e00 100644 --- a/drive-deposits-event-source/src/eb.rs +++ b/drive-deposits-event-source/src/eb.rs @@ -55,7 +55,9 @@ fn env_var_bool(name: &str) -> bool { #[instrument] fn use_localstack() -> bool { - env_var_bool("USE_LOCALSTACK") + let use_local = env_var_bool("USE_LOCALSTACK"); + debug!("use_localstack based on USE_LOCALSTACK: {}", use_local); + use_local } #[instrument] diff --git a/drive-deposits-grpc-server/Cargo.toml b/drive-deposits-grpc-server/Cargo.toml index 55efce7..381673c 100644 --- a/drive-deposits-grpc-server/Cargo.toml +++ b/drive-deposits-grpc-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-grpc-server" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-grpc-server/src/main.rs b/drive-deposits-grpc-server/src/main.rs index 7c70d97..994125f 100644 --- a/drive-deposits-grpc-server/src/main.rs +++ b/drive-deposits-grpc-server/src/main.rs @@ -9,11 +9,13 @@ use drive_deposits_grpc_server::service_router::app; async fn main() -> Result<(), Box> { registry() .with( - EnvFilter::try_from_default_env()?, // added in .cargo/config.toml.add_directive("drive_deposits_grpc=debug".parse()?), + EnvFilter::try_from_default_env() + .inspect_err(|err| println!(" error err is {:?}", err))?, // added in .cargo/config.toml.add_directive("drive_deposits_grpc=debug".parse()?), ) .with(tracing_subscriber::fmt::layer()) .init(); + println!("going to check RUST_LOG"); let rust_log = std::env::var("RUST_LOG")?; println!("RUST_LOG is {}", rust_log); diff --git a/drive-deposits-lambda-db-types/Cargo.toml b/drive-deposits-lambda-db-types/Cargo.toml index 6b807f7..e6c2b9f 100644 --- a/drive-deposits-lambda-db-types/Cargo.toml +++ b/drive-deposits-lambda-db-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-lambda-db-types" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-lambda-dynamodb-reader/Cargo.toml b/drive-deposits-lambda-dynamodb-reader/Cargo.toml index 0a76d9f..cf96767 100644 --- a/drive-deposits-lambda-dynamodb-reader/Cargo.toml +++ b/drive-deposits-lambda-dynamodb-reader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-lambda-dynamodb-reader" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-logs-lambda-target/Cargo.toml b/drive-deposits-logs-lambda-target/Cargo.toml index d6858c9..ec43115 100644 --- a/drive-deposits-logs-lambda-target/Cargo.toml +++ b/drive-deposits-logs-lambda-target/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-logs-lambda-target" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-proto-grpc-types/Cargo.toml b/drive-deposits-proto-grpc-types/Cargo.toml index 72deb9f..d091892 100644 --- a/drive-deposits-proto-grpc-types/Cargo.toml +++ b/drive-deposits-proto-grpc-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-proto-grpc-types" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-rest-gateway-server/Cargo.toml b/drive-deposits-rest-gateway-server/Cargo.toml index 9876da6..a3bba90 100644 --- a/drive-deposits-rest-gateway-server/Cargo.toml +++ b/drive-deposits-rest-gateway-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-rest-gateway-server" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/drive-deposits-rest-gateway-server/src/drive_deposits_client.rs b/drive-deposits-rest-gateway-server/src/drive_deposits_client.rs index 104d6ac..00b27b4 100644 --- a/drive-deposits-rest-gateway-server/src/drive_deposits_client.rs +++ b/drive-deposits-rest-gateway-server/src/drive_deposits_client.rs @@ -1,5 +1,6 @@ use axum::{async_trait, Json}; use mockall::automock; +use std::env::var; use tracing::{debug, debug_span, error, info}; use app_error::Error as AppError; @@ -52,7 +53,11 @@ pub async fn calculate_portfolio( ) }); - let client = DriveDepositsServiceClient::connect("http://[::]:50052") + // for docker compose dns GRPC_SERVER_ADDRESS=http://drive-deposits-grpc-server:50052 + let grpc_server_address = + var("GRPC_SERVER_ADDRESS").unwrap_or_else(|_| "http://[::]:50052".to_string()); + info!("grpc_server_address is: {}", grpc_server_address); + let client = DriveDepositsServiceClient::connect(grpc_server_address) .await .inspect_err(|err| { span.in_scope(|| error!("grpc client connection error: {:?}", err)); diff --git a/drive-deposits-rest-types/Cargo.toml b/drive-deposits-rest-types/Cargo.toml index dfe45ea..b0cd9f1 100644 --- a/drive-deposits-rest-types/Cargo.toml +++ b/drive-deposits-rest-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-deposits-rest-types" -version = "0.30.0" +version = "0.50.0" edition = "2021" [dependencies] diff --git a/justfile b/justfile index bb0b272..1462511 100644 --- a/justfile +++ b/justfile @@ -623,6 +623,36 @@ get-query-by-level-for-deposits-maturity-date: curl '{{aws_api_gateway_host}}/portfolios/{{aws_portfolio_uuid}}/by-level-for-deposits/maturity-date?order=asc&top_k=3' \ | jq + +# docker compose for local +# for server-based grpc and rest servers +compose-build-grpc-server: + docker compose --progress=plain -f compose.grpc.yaml build + +compose-build-rest-server: + docker compose --progress=plain -f compose.rest.yaml build + +compose-up-grpc-server:compose-build-grpc-server + docker compose --progress=plain -f compose.grpc.yaml up + +compose-up-rest-server:compose-build-rest-server + docker compose --progress=plain -f compose.rest.yaml up + +compose-build-grpc-server-no-cache: + docker compose --progress=plain -f compose.grpc.yaml build --no-cache + +compose-build-rest-server-no-cache: + docker compose --progress=plain -f compose.rest.yaml build --no-cache + +compose-up-grpc-server-no-cache:compose-build-grpc-server-no-cache + docker compose --progress=plain -f compose.grpc.yaml up + +compose-up-rest-server-no-cache:compose-build-rest-server-no-cache + docker compose --progress=plain -f compose.rest.yaml up + +docker-prune: + docker system prune -a + # for git release tags git-tag-add-local TAG: git tag -a {{TAG}} -m "Release version {{TAG}}"