feat: Add Dockerization support
This commit is contained in:
31
.dockerignore
Normal file
31
.dockerignore
Normal file
@@ -0,0 +1,31 @@
|
||||
# Rust
|
||||
target/
|
||||
**/*.rs.bk
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
|
||||
# Config and local data
|
||||
*.json
|
||||
!config.json.example
|
||||
!response.json.example
|
||||
status.json
|
||||
|
||||
# IDEs and Editors
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# CI/CD
|
||||
.gitea/
|
||||
.github/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
44
Dockerfile
Normal file
44
Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
||||
# Build stage
|
||||
FROM rust:alpine AS builder
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache musl-dev
|
||||
|
||||
WORKDIR /usr/src/dhl
|
||||
|
||||
# 1. Copy only the dependency manifests
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
|
||||
# 2. Create a dummy source file to build dependencies
|
||||
RUN mkdir src && echo "fn main() {}" > src/main.rs && \
|
||||
cargo build --release && \
|
||||
rm -rf src
|
||||
|
||||
# 3. Now copy the real source code
|
||||
COPY src ./src
|
||||
|
||||
# 4. Build the actual application
|
||||
# We touch the main file to ensure cargo rebuilds it
|
||||
RUN touch src/main.rs && cargo build --release
|
||||
|
||||
# Final stage
|
||||
FROM alpine:latest
|
||||
|
||||
# Set environment variable to signal the app it's running in Docker
|
||||
ENV DOCKER_CONTAINER=true
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the binary from the builder stage
|
||||
COPY --from=builder /usr/src/dhl/target/release/dhl /usr/local/bin/dhl
|
||||
|
||||
# Volume for configuration and response files
|
||||
VOLUME ["/app"]
|
||||
|
||||
# Default port
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["dhl"]
|
||||
46
README.md
46
README.md
@@ -99,6 +99,52 @@ cargo run
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
### Using with Docker
|
||||
|
||||
You can run DHL as a Docker container. The application automatically generates a default `config.json` and `response.json` if they are missing in the work directory.
|
||||
|
||||
#### Build the Image
|
||||
|
||||
```bash
|
||||
docker build -t dhl .
|
||||
```
|
||||
|
||||
#### Run with Docker CLI
|
||||
|
||||
To persist your configuration and response files, mount a local directory to `/app` in the container. The application will create default files in that directory if it is empty.
|
||||
|
||||
```bash
|
||||
# Create a folder for your mock data
|
||||
mkdir mock-data
|
||||
|
||||
# Run the container and mount the folder
|
||||
docker run -p 3000:3000 -v $(pwd)/mock-data:/app dhl
|
||||
```
|
||||
|
||||
#### Run with Docker Compose
|
||||
|
||||
An example `docker-compose.yml` is provided in the root directory:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
dhl:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./mock-data:/app
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
To start:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
**Note:** The default host is set to `0.0.0.0` for Docker compatibility. If you are using a custom `config.json`, ensure the `host` is set to `0.0.0.0`.
|
||||
|
||||
### Release Assets
|
||||
|
||||
When downloading a release, you will find:
|
||||
|
||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
services:
|
||||
dhl:
|
||||
build: .
|
||||
image: dhl:latest
|
||||
container_name: dhl
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
# Mount a local folder to /app to manage config.json and response files
|
||||
- ./mock-data:/app
|
||||
restart: unless-stopped
|
||||
@@ -1,28 +1,28 @@
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct TlsConfig {
|
||||
pub enabled: bool,
|
||||
pub cert_path: PathBuf,
|
||||
pub key_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct MaskingConfig {
|
||||
pub enabled: bool,
|
||||
pub headers: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct RouteConfig {
|
||||
pub path: String,
|
||||
pub response_file: PathBuf,
|
||||
pub status_code: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct Config {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
@@ -41,7 +41,11 @@ impl Config {
|
||||
})
|
||||
}
|
||||
Err(_) => {
|
||||
Self::default()
|
||||
let default_config = Self::default();
|
||||
if let Ok(json) = serde_json::to_string_pretty(&default_config) {
|
||||
let _ = fs::write("config.json", json);
|
||||
}
|
||||
default_config
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +54,7 @@ impl Config {
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
host: "127.0.0.1".to_string(),
|
||||
host: "0.0.0.0".to_string(),
|
||||
port: 3000,
|
||||
routes: vec![RouteConfig {
|
||||
path: "/".to_string(),
|
||||
|
||||
@@ -47,7 +47,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.layer(axum_middleware::from_fn_with_state(state.clone(), logging_middleware))
|
||||
.with_state(state);
|
||||
|
||||
let addr: SocketAddr = format!("{}:{}", config.host, config.port).parse()?;
|
||||
let mut host = config.host.clone();
|
||||
|
||||
// In Docker, we usually want to bind to 0.0.0.0 to be accessible
|
||||
if std::env::var("DOCKER_CONTAINER").is_ok() {
|
||||
host = "0.0.0.0".to_string();
|
||||
}
|
||||
|
||||
let addr: SocketAddr = format!("{}:{}", host, config.port).parse()?;
|
||||
|
||||
// 4. Start server
|
||||
if config.tls.enabled {
|
||||
|
||||
Reference in New Issue
Block a user