Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from djdongjin/ch5-deploy
Ch5 deploy
- Loading branch information
Showing
14 changed files
with
243 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.env | ||
target/ | ||
tests/ | ||
Dockerfile | ||
scripts/ | ||
migrations/ |
17 changes: 17 additions & 0 deletions
17
.sqlx/query-4b0ad859d2b54b0e4b34d2b56b993d973001526cc4ae39f99abfcc3f94d4a91d.json
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
FROM rust:1.77.0 as builder | ||
|
||
WORKDIR /app | ||
RUN apt update && apt install -y lld clang | ||
COPY . . | ||
ENV SQLX_OFFLINE true | ||
RUN cargo build --release | ||
|
||
FROM debian:bookworm-slim as runtime | ||
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/* | ||
WORKDIR /app | ||
COPY --from=builder /app/target/release/zero2prod zero2prod | ||
COPY configuration configuration | ||
ENV APP_ENVIRONMENT production | ||
ENTRYPOINT [ "./zero2prod" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
FROM lukemathwalker/cargo-chef:latest-rust-1.72.0 as chef | ||
WORKDIR /app | ||
RUN apt update && apt install -y lld clang | ||
|
||
FROM chef as planner | ||
COPY . . | ||
# Compute a lock-like file for our project | ||
RUN cargo chef prepare --recipe-path recipe.json | ||
|
||
FROM chef as builder | ||
COPY --from=planner /app/recipe.json recipe.json | ||
# Build our project dependencies | ||
RUN cargo chef cook --release --recipe-path recipe.json | ||
# Up to this point, if our dependency tree stays the same, | ||
# all layers should be cached. | ||
COPY . . | ||
ENV SQLX_OFFLINE true | ||
RUN cargo build --release --bin zero2prod | ||
|
||
FROM debian:bookworm-slim as runtime | ||
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/* | ||
WORKDIR /app | ||
COPY --from=builder /app/target/release/zero2prod zero2prod | ||
COPY configuration configuration | ||
ENV APP_ENVIRONMENT production | ||
ENTRYPOINT [ "./zero2prod" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
application_port: 8000 | ||
application: | ||
port: 8000 | ||
database: | ||
host: "localhost" | ||
port: 5432 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
application: | ||
host: 127.0.0.1 | ||
database: | ||
require_ssl: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
application: | ||
host: 0.0.0.0 | ||
database: | ||
require_ssl: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
name: zero2prod | ||
# See https://www.digitalocean.com/docs/app-platform/#regional-availability for the available options | ||
# You can get region slugs from https://www.digitalocean.com/docs/platform/availability-matrix/ | ||
# `fra` stands for Frankfurt (Germany - EU) | ||
region: fra | ||
services: | ||
- name: zero2prod | ||
# Relative to the repository root | ||
dockerfile_path: Dockerfile | ||
source_dir: . | ||
github: | ||
branch: root-chapter-05 | ||
deploy_on_push: true | ||
repo: djdongjin/zero2prod | ||
# Active probe used by DigitalOcean's to ensure our application is healthy | ||
health_check: | ||
# The path to our health check endpoint! It turned out to be useful in the end! | ||
http_path: /health_check | ||
# The port the application will be listening on for incoming requests | ||
# It should match what we specify in our configuration.yaml file! | ||
http_port: 8000 | ||
# For production workloads we'd go for at least two! | ||
instance_count: 1 | ||
# Let's keep the bill lean for now... | ||
instance_size_slug: basic-xxs | ||
# All incoming requests should be routed to our app | ||
routes: | ||
- path: / | ||
envs: | ||
- key: APP_DATABASE__USERNAME | ||
scope: RUN_TIME | ||
value: ${newsletter.USERNAME} | ||
- key: APP_DATABASE__PASSWORD | ||
scope: RUN_TIME | ||
value: ${newsletter.PASSWORD} | ||
- key: APP_DATABASE__HOST | ||
scope: RUN_TIME | ||
value: ${newsletter.HOSTNAME} | ||
- key: APP_DATABASE__PORT | ||
scope: RUN_TIME | ||
value: ${newsletter.PORT} | ||
- key: APP_DATABASE__DATABASE_NAME | ||
scope: RUN_TIME | ||
value: ${newsletter.DATABASE} | ||
databases: | ||
# PG = Postgres | ||
- engine: PG | ||
# Database name | ||
name: newsletter | ||
# Again, let's keep the bill lean | ||
num_nodes: 1 | ||
size: db-s-dev-database | ||
# Postgres version - using the latest here | ||
version: "14" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,105 @@ | ||
use secrecy::{ExposeSecret, Secret}; | ||
use serde_aux::field_attributes::deserialize_number_from_string; | ||
use sqlx::postgres::{PgConnectOptions, PgSslMode}; | ||
use sqlx::ConnectOptions; | ||
|
||
#[derive(serde::Deserialize)] | ||
pub struct Settings { | ||
pub database: DatabseSettings, | ||
pub application_port: u16, | ||
pub application: ApplicationSettings, | ||
} | ||
|
||
#[derive(serde::Deserialize)] | ||
pub struct DatabseSettings { | ||
pub username: String, | ||
pub password: Secret<String>, | ||
pub host: String, | ||
#[serde(deserialize_with = "deserialize_number_from_string")] | ||
pub port: u16, | ||
pub database_name: String, | ||
// Determine if we demand the connection to be encrypted or not | ||
pub require_ssl: bool, | ||
} | ||
|
||
#[derive(serde::Deserialize)] | ||
pub struct ApplicationSettings { | ||
pub host: String, | ||
pub port: u16, | ||
} | ||
|
||
impl DatabseSettings { | ||
pub fn connection_string(&self) -> Secret<String> { | ||
Secret::new(format!( | ||
"postgres://{}:{}@{}:{}/{}", | ||
self.username, | ||
self.password.expose_secret(), | ||
self.host, | ||
self.port, | ||
self.database_name | ||
)) | ||
pub fn without_db(&self) -> PgConnectOptions { | ||
let ssl_mode = if self.require_ssl { | ||
PgSslMode::Require | ||
} else { | ||
PgSslMode::Prefer | ||
}; | ||
|
||
PgConnectOptions::new() | ||
.username(&self.username) | ||
.password(self.password.expose_secret()) | ||
.host(&self.host) | ||
.port(self.port) | ||
.ssl_mode(ssl_mode) | ||
} | ||
|
||
pub fn connection_string_without_db(&self) -> Secret<String> { | ||
Secret::new(format!( | ||
"postgres://{}:{}@{}:{}", | ||
self.username, | ||
self.password.expose_secret(), | ||
self.host, | ||
self.port | ||
)) | ||
pub fn with_db(&self) -> PgConnectOptions { | ||
let options = self.without_db().database(&self.database_name); | ||
options.log_statements(tracing_log::log::LevelFilter::Trace) | ||
} | ||
} | ||
|
||
pub fn get_configuration() -> Result<Settings, config::ConfigError> { | ||
let base_path = std::env::current_dir().expect("Failed to determine the current directory"); | ||
let config_dir = base_path.join("configuration"); | ||
let environment: Environment = std::env::var("APP_ENVIRONMENT") | ||
.unwrap_or_else(|_| "local".into()) | ||
.try_into() | ||
.expect("Failed to parse APP_ENVIRONMENT"); | ||
let environment_filename = format!("{}.yaml", environment.as_str()); | ||
|
||
let settings = config::Config::builder() | ||
.add_source(config::File::new( | ||
"configuration.yaml", | ||
config::FileFormat::Yaml, | ||
)) | ||
.add_source(config::File::from(config_dir.join("base.yaml"))) | ||
.add_source(config::File::from(config_dir.join(environment_filename))) | ||
// Add in settings from environment variables (with a prefix of APP and | ||
// '__' as separator) | ||
// E.g. `APP_APPLICATION__PORT=5001 would set `Settings.application.port` | ||
.add_source( | ||
config::Environment::with_prefix("APP") | ||
.prefix_separator("_") | ||
.separator("__"), | ||
) | ||
.build()?; | ||
|
||
settings.try_deserialize::<Settings>() | ||
} | ||
|
||
pub enum Environment { | ||
Local, | ||
Production, | ||
} | ||
|
||
impl Environment { | ||
pub fn as_str(&self) -> &'static str { | ||
match self { | ||
Environment::Local => "local", | ||
Environment::Production => "production", | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<String> for Environment { | ||
type Error = String; | ||
|
||
fn try_from(value: String) -> Result<Self, Self::Error> { | ||
match value.to_lowercase().as_str() { | ||
"local" => Ok(Self::Local), | ||
"production" => Ok(Self::Production), | ||
other => Err(format!( | ||
"{} is not a suppported environment. \ | ||
Use either `local` or `production`.", | ||
other | ||
)), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters