#!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=00-platform-guard.inc source "$SCRIPT_DIR/00-platform-guard.inc" SOURCE_CONFIG="$SCRIPT_DIR/../files/docker/daemon.json" DOCKER_CONFIG="/etc/docker/daemon.json" temporary_files=() cleanup() { local path for path in "${temporary_files[@]}"; do rm -f "$path" done } trap cleanup EXIT backup_file() { local path="$1" local backup backup="${path}.$(date '+%Y%m%d-%H%M%S').bak" install -m 0644 "$path" "$backup" printf 'INFO: backed up %s to %s\n' "$path" "$backup" } if ((EUID != 0)); then printf 'CRITICAL: Docker setup must run as root\n' >&2 exit 2 fi require_supported_ubuntu for command_name in apt-get apt-cache; do if ! command -v "$command_name" >/dev/null 2>&1; then printf 'CRITICAL: required command is missing: %s\n' "$command_name" >&2 exit 2 fi done apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl gnupg jq if apt-cache show docker.io >/dev/null 2>&1; then packages=(docker.io) if apt-cache show docker-compose-v2 >/dev/null 2>&1; then packages+=(docker-compose-v2) else printf 'WARNING: docker-compose-v2 is unavailable from Ubuntu repositories\n' fi else printf 'WARNING: docker.io is unavailable; configuring Docker official repository\n' install -d -m 0755 /etc/apt/keyrings tmp_key="$(mktemp)" temporary_files+=("$tmp_key") curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | gpg --dearmor --yes -o "$tmp_key" if [[ ! -f /etc/apt/keyrings/docker.gpg ]] || \ ! cmp -s "$tmp_key" /etc/apt/keyrings/docker.gpg; then if [[ -f /etc/apt/keyrings/docker.gpg ]]; then backup_file /etc/apt/keyrings/docker.gpg fi install -m 0644 "$tmp_key" /etc/apt/keyrings/docker.gpg fi # shellcheck disable=SC1091 source /etc/os-release architecture="$(dpkg --print-architecture)" tmp_repository="$(mktemp)" temporary_files+=("$tmp_repository") printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu %s stable\n' \ "$architecture" "${VERSION_CODENAME:?}" \ >"$tmp_repository" if [[ ! -f /etc/apt/sources.list.d/docker.list ]] || \ ! cmp -s "$tmp_repository" /etc/apt/sources.list.d/docker.list; then if [[ -f /etc/apt/sources.list.d/docker.list ]]; then backup_file /etc/apt/sources.list.d/docker.list fi install -m 0644 "$tmp_repository" /etc/apt/sources.list.d/docker.list fi apt-get update packages=(docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin) fi DEBIAN_FRONTEND=noninteractive apt-get install -y "${packages[@]}" install -d -m 0755 /etc/docker if [[ ! -r "$SOURCE_CONFIG" ]]; then printf 'CRITICAL: Docker configuration template is missing: %s\n' "$SOURCE_CONFIG" >&2 exit 2 fi jq empty "$SOURCE_CONFIG" tmp_config="$(mktemp)" temporary_files+=("$tmp_config") if [[ -f "$DOCKER_CONFIG" ]]; then if ! jq empty "$DOCKER_CONFIG" >/dev/null 2>&1; then printf 'CRITICAL: %s is invalid JSON; refusing to overwrite it\n' "$DOCKER_CONFIG" >&2 exit 1 fi jq '. + { "log-driver": "json-file", "log-opts": ((."log-opts" // {}) + {"max-size": "50m", "max-file": "5"}) }' "$DOCKER_CONFIG" >"$tmp_config" else install -m 0644 "$SOURCE_CONFIG" "$tmp_config" fi jq empty "$tmp_config" config_changed=0 if [[ ! -f "$DOCKER_CONFIG" ]] || ! cmp -s "$tmp_config" "$DOCKER_CONFIG"; then if [[ -f "$DOCKER_CONFIG" ]]; then backup_file "$DOCKER_CONFIG" fi install -m 0644 "$tmp_config" "$DOCKER_CONFIG" config_changed=1 printf 'OK: installed Docker daemon log limits\n' else printf 'OK: Docker daemon configuration is already current\n' fi systemctl enable --now docker if ((config_changed == 1)); then systemctl restart docker fi docker version if docker compose version >/dev/null 2>&1; then docker compose version else printf 'WARNING: Docker Compose v2 is unavailable\n' fi printf 'OK: Docker setup completed\n'