From a107caac994e079ebca01e7d5a10961bdccc5ff4 Mon Sep 17 00:00:00 2001 From: wheelz Date: Tue, 8 Sep 2026 19:09:33 +0000 Subject: [PATCH] Add optional Portainer install --- README.md | 41 ++++++++++++++++++-- install-docker.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 129 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6c92dcc..3cad5de 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ It installs: - Docker Buildx plugin - Docker Compose plugin -It can also optionally add a chosen Linux user to the `docker` group so Docker commands can be run without `sudo` after the user logs out/in. +It can also optionally add a chosen Linux user to the `docker` group so Docker commands can be run without `sudo` after the user logs out/in. If requested, it can install Portainer CE as a local Docker container too. ## One-command install @@ -32,6 +32,18 @@ Install Docker and add a specific user to the docker group: curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --user obin ``` +Install Docker, add the current SSH/login user, and install Portainer CE: + +```bash +curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --current-user --portainer +``` + +Install Docker and Portainer CE only: + +```bash +curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --portainer +``` + Non-interactive install without adding a docker user: ```bash @@ -54,9 +66,13 @@ The old `Docker-Install.sh` filename still exists as a compatibility wrapper. ```text --user USER Add USER to the docker group after install. --current-user Add the invoking SSH/login user to the docker group. ---no-docker-user Do not add anyone to the docker group. --y, --yes Non-interactive defaults. Skips docker group unless --user/--current-user is supplied. --h, --help Show help. +--no-docker-user Do not add anyone to the docker group. +--portainer Install or start Portainer CE after Docker install. +--portainer-port PORT Host port for Portainer HTTPS UI. Default: 9443. +--portainer-edge-port PORT Host port for Portainer Edge agent tunnel. Default: 8000. +--portainer-image IMAGE Portainer image to run. Default: portainer/portainer-ce:lts. +-y, --yes Non-interactive defaults. Skips docker group unless --user/--current-user is supplied. +-h, --help Show help. ``` ## After adding a user to the docker group @@ -73,6 +89,23 @@ Then verify Docker works without sudo: docker run --rm hello-world ``` +## Portainer + +When `--portainer` is supplied, the installer creates a persistent Docker volume named `portainer_data` and starts Portainer CE with: + +- HTTPS UI: `https://:9443` +- Edge agent tunnel: `:8000` +- Container name: `portainer` +- Restart policy: `always` + +Portainer uses a self-signed certificate by default, so the browser warning is expected on first visit. + +Custom Portainer UI port example: + +```bash +curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --current-user --portainer --portainer-port 9444 +``` + ## Supported systems - Ubuntu diff --git a/install-docker.sh b/install-docker.sh index 14628a0..079afd6 100755 --- a/install-docker.sh +++ b/install-docker.sh @@ -5,26 +5,36 @@ SCRIPT_NAME="$(basename "$0")" DEFAULT_USER="${SUDO_USER:-${USER:-}}" DOCKER_USER="" ADD_DOCKER_GROUP="ask" +INSTALL_PORTAINER="no" +PORTAINER_HTTPS_PORT="9443" +PORTAINER_EDGE_PORT="8000" +PORTAINER_IMAGE="portainer/portainer-ce:lts" usage() { cat <<'USAGE' Install Docker Engine and Docker Compose plugin on a fresh Debian/Ubuntu server. +Optionally install Portainer CE after Docker is running. Usage: ./install-docker.sh [options] curl -fsSL /install-docker.sh | bash -s -- [options] Options: - --user USER Add USER to the docker group after install. - --current-user Add the invoking user to the docker group. - --no-docker-user Do not add anyone to the docker group. - -y, --yes Non-interactive defaults. Installs Docker and skips docker group unless --user/--current-user is also supplied. - -h, --help Show this help. + --user USER Add USER to the docker group after install. + --current-user Add the invoking user to the docker group. + --no-docker-user Do not add anyone to the docker group. + --portainer Install or start Portainer CE after Docker install. + --portainer-port PORT Host port for Portainer HTTPS UI. Default: 9443. + --portainer-edge-port PORT Host port for Portainer Edge agent tunnel. Default: 8000. + --portainer-image IMAGE Portainer image to run. Default: portainer/portainer-ce:lts. + -y, --yes Non-interactive defaults. Installs Docker and skips docker group unless --user/--current-user is also supplied. + -h, --help Show this help. Examples: curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --user obin curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --current-user + curl -fsSL https://gitea.wheelytho.com/Wheelz/Docker-Install/raw/branch/main/install-docker.sh | bash -s -- --current-user --portainer USAGE } @@ -32,6 +42,47 @@ log() { printf '\n[Docker-Install] %s\n' "$*"; } warn() { printf '\n[Docker-Install WARNING] %s\n' "$*" >&2; } fail() { printf '\n[Docker-Install ERROR] %s\n' "$*" >&2; exit 1; } +require_port_number() { + local name="$1" + local value="$2" + [[ "$value" =~ ^[0-9]+$ ]] || fail "$name must be a number. Got: $value" + (( value >= 1 && value <= 65535 )) || fail "$name must be between 1 and 65535. Got: $value" +} + +install_portainer() { + log "Installing Portainer CE" + + require_port_number "--portainer-port" "$PORTAINER_HTTPS_PORT" + require_port_number "--portainer-edge-port" "$PORTAINER_EDGE_PORT" + + $SUDO docker volume create portainer_data >/dev/null + + if $SUDO docker container inspect portainer >/dev/null 2>&1; then + if [[ "$($SUDO docker inspect -f '{{.State.Running}}' portainer 2>/dev/null)" == "true" ]]; then + log "Portainer container already exists and is running" + else + log "Portainer container already exists; starting it" + $SUDO docker start portainer >/dev/null + fi + else + $SUDO docker run -d \ + --name portainer \ + --restart=always \ + -p "${PORTAINER_EDGE_PORT}:8000" \ + -p "${PORTAINER_HTTPS_PORT}:9443" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v portainer_data:/data \ + "$PORTAINER_IMAGE" >/dev/null + fi + + local host_ip + host_ip="$(hostname -I 2>/dev/null | awk '{print $1}')" + [[ -n "$host_ip" ]] || host_ip="" + + log "Portainer is available at: https://${host_ip}:${PORTAINER_HTTPS_PORT}" + warn "Portainer uses a self-signed certificate by default, so your browser may show a warning." +} + while [[ $# -gt 0 ]]; do case "$1" in --user) @@ -51,6 +102,25 @@ while [[ $# -gt 0 ]]; do DOCKER_USER="" shift ;; + --portainer) + INSTALL_PORTAINER="yes" + shift + ;; + --portainer-port) + [[ $# -ge 2 ]] || fail "--portainer-port requires a port number" + PORTAINER_HTTPS_PORT="$2" + shift 2 + ;; + --portainer-edge-port) + [[ $# -ge 2 ]] || fail "--portainer-edge-port requires a port number" + PORTAINER_EDGE_PORT="$2" + shift 2 + ;; + --portainer-image) + [[ $# -ge 2 ]] || fail "--portainer-image requires an image name" + PORTAINER_IMAGE="$2" + shift 2 + ;; -y|--yes) [[ "$ADD_DOCKER_GROUP" == "ask" ]] && ADD_DOCKER_GROUP="no" shift @@ -140,6 +210,10 @@ $SUDO docker --version docker compose version || $SUDO docker compose version $SUDO docker run --rm hello-world >/dev/null +if [[ "$INSTALL_PORTAINER" == "yes" ]]; then + install_portainer +fi + cat <:${PORTAINER_HTTPS_PORT} +EOF +else + cat <