mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Add distroless Dockerfile and implement internal health check (#3366)
- rslib(http_server): add `is_running()` method - rslib(sync): introduce `--healthcheck` argument for health probe in distroless - doc(syncserver): add table comparing Dockerfile and Dockerfile.distroless - Expand cross-platform support with distroless - add `Dockerfile.distroless` - Dockerfile: bump rust `1.79` to `1.80.1` - Dockerfile: bump alpine `3.20` to `3.20.2` Note: Implemented an internal health check because distroless images do not include curl, which is used to reduce image size and attack surface. For more details, see https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/ https://github.com/GoogleContainerTools/distroless fix: failed: check:format:rust typo remove extra space fix failed:check:format:rust update doc fetch `host` and `port` using envy fix: failed: check:format:rust Update doc + add dockerignore - dockerignore: This helps avoid sending unwanted files and directories to the builder - add new line - I am still experimenting cross platform compilation, I am getting 4.337 From https://github.com/ankitects/rust-url 4.337 * [new ref] bb930b8d089f4d30d7d19c12e54e66191de47b88 -> refs/commit/bb930b8d089f4d30d7d19c12e54e66191de47b88 4.397 error: failed to get `percent-encoding-iri` as a dependency of package `anki v0.0.0 (/app/rslib)` still checking what could be the issue fix: failed: check:format:dprint
This commit is contained in:
parent
be2f013cb7
commit
83fe301c1c
6 changed files with 71 additions and 7 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules/
|
||||||
|
target/
|
||||||
|
out/
|
|
@ -1,14 +1,15 @@
|
||||||
FROM rust:1.79-alpine3.20 AS builder
|
FROM rust:1.80.1-alpine3.20 AS builder
|
||||||
|
|
||||||
ARG ANKI_VERSION
|
ARG ANKI_VERSION
|
||||||
|
|
||||||
RUN apk update && apk add --no-cache build-base protobuf && rm -rf /var/cache/apk/*
|
RUN apk update && apk add --no-cache build-base protobuf && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
RUN cargo install --git https://github.com/ankitects/anki.git \
|
RUN cargo install --git https://github.com/ankitects/anki.git \
|
||||||
--tag ${ANKI_VERSION} \
|
--tag ${ANKI_VERSION} \
|
||||||
--root /anki-server \
|
--root /anki-server \
|
||||||
anki-sync-server
|
anki-sync-server
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20.2
|
||||||
|
|
||||||
RUN adduser -D -h /home/anki anki
|
RUN adduser -D -h /home/anki anki
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ EXPOSE ${SYNC_PORT}
|
||||||
|
|
||||||
CMD ["anki-sync-server"]
|
CMD ["anki-sync-server"]
|
||||||
|
|
||||||
# This health check will work for Anki versions 24.06.3 and newer.
|
# This health check will work for Anki versions 24.08.x and newer.
|
||||||
# For older versions, it may incorrectly report an unhealthy status, which should not be the case.
|
# For older versions, it may incorrectly report an unhealthy status, which should not be the case.
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD wget -qO- http://localhost:${SYNC_PORT}/health || exit 1
|
CMD wget -qO- http://localhost:${SYNC_PORT}/health || exit 1
|
||||||
|
|
27
docs/syncserver/Dockerfile.distroless
Normal file
27
docs/syncserver/Dockerfile.distroless
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
FROM rust:1.80.1 AS builder
|
||||||
|
|
||||||
|
ARG ANKI_VERSION
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y build-essential protobuf-compiler && apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN cargo install --git https://github.com/ankitects/anki.git \
|
||||||
|
--tag ${ANKI_VERSION} \
|
||||||
|
--root /anki-server \
|
||||||
|
anki-sync-server
|
||||||
|
|
||||||
|
FROM gcr.io/distroless/cc-debian12
|
||||||
|
|
||||||
|
COPY --from=builder /anki-server/bin/anki-sync-server /usr/bin/anki-sync-server
|
||||||
|
|
||||||
|
ENV SYNC_PORT=${SYNC_PORT:-"8080"}
|
||||||
|
|
||||||
|
EXPOSE ${SYNC_PORT}
|
||||||
|
|
||||||
|
CMD ["anki-sync-server"]
|
||||||
|
|
||||||
|
# This health check will work for Anki versions 24.08.x and newer.
|
||||||
|
# For older versions, it may incorrectly report an unhealthy status, which should not be the case.
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD ["anki-sync-server", "--healthcheck"]
|
||||||
|
|
||||||
|
LABEL maintainer="Jean Khawand <jk@jeankhawand.com>"
|
|
@ -10,13 +10,26 @@ the build products and runtime dependencies from the rest of your system.
|
||||||
|
|
||||||
- [x] [Docker](https://docs.docker.com/get-started/)
|
- [x] [Docker](https://docs.docker.com/get-started/)
|
||||||
|
|
||||||
|
| **Aspect** | **Dockerfile** | **Dockerfile.distroless** |
|
||||||
|
| ---------------------- | ---------------------------------------------------------- | --------------------------------------------------------- |
|
||||||
|
| **Shell & Tools** | ✅ Includes shell and tools | ❌ Minimal, no shell or tools |
|
||||||
|
| **Debugging** | ✅ Easier debugging with shell and tools | ❌ Harder to debug due to minimal environment |
|
||||||
|
| **Health Checks** | ✅ Supports complex health checks | ❌ Health checks need to be simple or directly executable |
|
||||||
|
| **Image Size** | ❌ Larger image size | ✅ Smaller image size |
|
||||||
|
| **Customization** | ✅ Easier to customize with additional packages | ❌ Limited customization options |
|
||||||
|
| **Attack Surface** | ❌ Larger attack surface due to more installed packages | ✅ Reduced attack surface |
|
||||||
|
| **Libraries** | ✅ More libraries available | ❌ Limited libraries |
|
||||||
|
| **Start-up Time** | ❌ Slower start-up time due to larger image size | ✅ Faster start-up time |
|
||||||
|
| **Tool Compatibility** | ✅ Compatible with more tools and libraries | ❌ Compatibility limitations with certain tools |
|
||||||
|
| **Maintenance** | ❌ Higher maintenance due to larger image and dependencies | ✅ Lower maintenance with minimal base image |
|
||||||
|
|
||||||
# Building image
|
# Building image
|
||||||
|
|
||||||
To proceed with building, you must specify the Anki version you want, by replacing `<version>` with something like `23.12.1`.
|
To proceed with building, you must specify the Anki version you want, by replacing `<version>` with something like `23.12.1` and `<Dockerfile>` with the chosen Dockerfile (e.g., `Dockerfile` or `Dockerfile.distroless`)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Ensure you are running this command inside /docs/syncserver
|
# Execute this command from the root directory of your project
|
||||||
docker build --no-cache --build-arg ANKI_VERSION=<version> -t anki-sync-server .
|
docker build -f docs/syncserver/<Dockerfile> --no-cache --build-arg ANKI_VERSION=<version> -t anki-sync-server .
|
||||||
```
|
```
|
||||||
|
|
||||||
# Run container
|
# Run container
|
||||||
|
|
|
@ -219,7 +219,12 @@ impl SimpleServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn is_running() -> bool {
|
||||||
|
let config = envy::prefixed("SYNC_")
|
||||||
|
.from_env::<SyncServerConfig>()
|
||||||
|
.unwrap();
|
||||||
|
std::net::TcpStream::connect(&format!("{}:{}", config.host, config.port)).is_ok()
|
||||||
|
}
|
||||||
pub fn new(base_folder: &Path) -> error::Result<Self, Whatever> {
|
pub fn new(base_folder: &Path) -> error::Result<Self, Whatever> {
|
||||||
let inner = SimpleServerInner::new_from_env(base_folder)?;
|
let inner = SimpleServerInner::new_from_env(base_folder)?;
|
||||||
Ok(SimpleServer {
|
Ok(SimpleServer {
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
use anki::log::set_global_logger;
|
use anki::log::set_global_logger;
|
||||||
use anki::sync::http_server::SimpleServer;
|
use anki::sync::http_server::SimpleServer;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
if let Some(arg) = env::args().nth(1) {
|
||||||
|
if arg == "--healthcheck" {
|
||||||
|
run_health_check();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if env::var("RUST_LOG").is_err() {
|
if env::var("RUST_LOG").is_err() {
|
||||||
env::set_var("RUST_LOG", "anki=info")
|
env::set_var("RUST_LOG", "anki=info")
|
||||||
}
|
}
|
||||||
set_global_logger(None).unwrap();
|
set_global_logger(None).unwrap();
|
||||||
println!("{}", SimpleServer::run());
|
println!("{}", SimpleServer::run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_health_check() {
|
||||||
|
if SimpleServer::is_running() {
|
||||||
|
process::exit(0);
|
||||||
|
} else {
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue