diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..08933861641 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +node_modules/ +target/ +out/ \ No newline at end of file diff --git a/docs/syncserver/Dockerfile b/docs/syncserver/Dockerfile index b45eb2e6871..2080f777870 100644 --- a/docs/syncserver/Dockerfile +++ b/docs/syncserver/Dockerfile @@ -1,14 +1,15 @@ -FROM rust:1.79-alpine3.20 AS builder +FROM rust:1.80.1-alpine3.20 AS builder ARG ANKI_VERSION 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 \ --tag ${ANKI_VERSION} \ --root /anki-server \ anki-sync-server -FROM alpine:3.20 +FROM alpine:3.20.2 RUN adduser -D -h /home/anki anki @@ -25,7 +26,7 @@ EXPOSE ${SYNC_PORT} 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. HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget -qO- http://localhost:${SYNC_PORT}/health || exit 1 diff --git a/docs/syncserver/Dockerfile.distroless b/docs/syncserver/Dockerfile.distroless new file mode 100644 index 00000000000..b53a9c62b2e --- /dev/null +++ b/docs/syncserver/Dockerfile.distroless @@ -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 " \ No newline at end of file diff --git a/docs/syncserver/README.md b/docs/syncserver/README.md index 4dc78a54c45..ccb7815d117 100644 --- a/docs/syncserver/README.md +++ b/docs/syncserver/README.md @@ -10,13 +10,26 @@ the build products and runtime dependencies from the rest of your system. - [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 -To proceed with building, you must specify the Anki version you want, by replacing `` with something like `23.12.1`. +To proceed with building, you must specify the Anki version you want, by replacing `` with something like `23.12.1` and `` with the chosen Dockerfile (e.g., `Dockerfile` or `Dockerfile.distroless`) ```bash -# Ensure you are running this command inside /docs/syncserver -docker build --no-cache --build-arg ANKI_VERSION= -t anki-sync-server . +# Execute this command from the root directory of your project +docker build -f docs/syncserver/ --no-cache --build-arg ANKI_VERSION= -t anki-sync-server . ``` # Run container diff --git a/rslib/src/sync/http_server/mod.rs b/rslib/src/sync/http_server/mod.rs index 697839b8460..7759f3383ad 100644 --- a/rslib/src/sync/http_server/mod.rs +++ b/rslib/src/sync/http_server/mod.rs @@ -219,7 +219,12 @@ impl SimpleServer { } } } - + pub fn is_running() -> bool { + let config = envy::prefixed("SYNC_") + .from_env::() + .unwrap(); + std::net::TcpStream::connect(&format!("{}:{}", config.host, config.port)).is_ok() + } pub fn new(base_folder: &Path) -> error::Result { let inner = SimpleServerInner::new_from_env(base_folder)?; Ok(SimpleServer { diff --git a/rslib/sync/main.rs b/rslib/sync/main.rs index 80fd3007b7f..0ec1fcb200d 100644 --- a/rslib/sync/main.rs +++ b/rslib/sync/main.rs @@ -1,14 +1,29 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html use std::env; +use std::process; use anki::log::set_global_logger; use anki::sync::http_server::SimpleServer; fn main() { + if let Some(arg) = env::args().nth(1) { + if arg == "--healthcheck" { + run_health_check(); + return; + } + } if env::var("RUST_LOG").is_err() { env::set_var("RUST_LOG", "anki=info") } set_global_logger(None).unwrap(); println!("{}", SimpleServer::run()); } + +fn run_health_check() { + if SimpleServer::is_running() { + process::exit(0); + } else { + process::exit(1); + } +}