diff --git a/docs/syncserver/Dockerfile b/docs/syncserver/Dockerfile index 89fcc008f..b45eb2e68 100644 --- a/docs/syncserver/Dockerfile +++ b/docs/syncserver/Dockerfile @@ -1,14 +1,14 @@ -FROM rust:1.76-alpine3.19 AS builder +FROM rust:1.79-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 +--tag ${ANKI_VERSION} \ +--root /anki-server \ +anki-sync-server -FROM alpine:3.19.1 +FROM alpine:3.20 RUN adduser -D -h /home/anki anki @@ -25,8 +25,9 @@ EXPOSE ${SYNC_PORT} CMD ["anki-sync-server"] -# TODO - consider exposing endpoint /health to check on health cause currently it will return 404 error -# HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ -# CMD wget -qO- http://localhost:${SYNC_PORT} || exit 1 +# This health check will work for Anki versions 24.06.3 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 LABEL maintainer="Jean Khawand " \ No newline at end of file diff --git a/rslib/src/sync/http_server/mod.rs b/rslib/src/sync/http_server/mod.rs index 786d75eb6..697839b84 100644 --- a/rslib/src/sync/http_server/mod.rs +++ b/rslib/src/sync/http_server/mod.rs @@ -20,6 +20,7 @@ use std::sync::Mutex; use anki_io::create_dir_all; use axum::extract::DefaultBodyLimit; +use axum::routing::get; use axum::Router; use axum_client_ip::SecureClientIpSource; use pbkdf2::password_hash::PasswordHash; @@ -41,6 +42,7 @@ use crate::sync::error::OrHttpErr; use crate::sync::http_server::logging::with_logging_layer; use crate::sync::http_server::media_manager::ServerMediaManager; use crate::sync::http_server::routes::collection_sync_router; +use crate::sync::http_server::routes::health_check_handler; use crate::sync::http_server::routes::media_sync_router; use crate::sync::http_server::user::User; use crate::sync::login::HostKeyRequest; @@ -240,6 +242,7 @@ impl SimpleServer { Router::new() .nest("/sync", collection_sync_router()) .nest("/msync", media_sync_router()) + .route("/health", get(health_check_handler)) .with_state(server) .layer(DefaultBodyLimit::max(*MAXIMUM_SYNC_PAYLOAD_BYTES)) .layer(config.ip_header.into_extension()), diff --git a/rslib/src/sync/http_server/routes.rs b/rslib/src/sync/http_server/routes.rs index a8fd90342..dd4c0d3bd 100644 --- a/rslib/src/sync/http_server/routes.rs +++ b/rslib/src/sync/http_server/routes.rs @@ -4,6 +4,8 @@ use axum::extract::Path; use axum::extract::Query; use axum::extract::State; +use axum::http::StatusCode; +use axum::response::IntoResponse; use axum::response::Response; use axum::routing::get; use axum::routing::post; @@ -86,6 +88,10 @@ async fn media_begin_post( media_sync_handler(Path(MediaSyncMethod::Begin), server, req.into_output_type()).await } +pub async fn health_check_handler() -> impl IntoResponse { + StatusCode::OK +} + async fn media_sync_handler( Path(method): Path, State(server): State

,