diff --git a/README.md b/README.md index 32943c1..14c8e98 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,39 @@ The latest image is available on DockerHub at `listmonk/listmonk:latest`. Use th ```bash mkdir listmonk-demo -sh -c "$(curl -sSL https://raw.githubusercontent.com/knadh/listmonk/master/install-demo.sh)" +sh -c "$(curl -fsSL https://raw.githubusercontent.com/knadh/listmonk/master/install-demo.sh)" ``` The demo does not persist Postgres after the containers are removed. DO NOT use this demo setup in production. #### Production + +##### Easy Docker install + +This setup is recommended if you want to _quickly_ setup `listmonk` in production. + +```bash +mkdir listmonk +sh -c "$(curl -fsSL https://raw.githubusercontent.com/knadh/listmonk/master/install-prod.sh)" +``` + +The above shell script performs the following actions: + +- Downloads `docker-compose.yml` and generates a `config.toml`. +- Runs a Postgres container and installs the database schema. +- Runs the `listmonk` container. + +**NOTE**: It's recommended to examine the contents of the shell script, before running in your environment. + +##### Manual Docker install + +The following workflow is recommended to setup `listmonk` manually using `docker-compose`. You are encouraged to customise the contents of `docker-compose.yml` to your needs. The overall setup looks like: + - `docker-compose up db` to run the Postgres DB. -- `docker-compose run --rm app ./listmonk --install` to setup the DB (or `--upgrade` to upgrade an existing DB) +- `docker-compose run --rm app ./listmonk --install` to setup the DB (or `--upgrade` to upgrade an existing DB). +- Copy `config.toml.sample` to your directory and make the following changes: + - `app.address` => `0.0.0.0:9000` (Port forwarding on Docker will work only if the app is advertising on all interfaces.) + - `db.host` => `listmonk_db` (Container Name of the DB container) - Run `docker-compose up app` and visit `http://localhost:9000`. More information on [docs](https://listmonk.app/docs). diff --git a/docker-compose.yml b/docker-compose.yml index 77fbf59..2fe8a81 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,10 +23,16 @@ x-db-defaults: &db-defaults - POSTGRES_USER=listmonk - POSTGRES_DB=listmonk restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U listmonk"] + interval: 10s + timeout: 5s + retries: 6 services: db: <<: *db-defaults + container_name: listmonk_db volumes: - type: volume source: listmonk-data @@ -34,14 +40,19 @@ services: app: <<: *app-defaults + container_name: listmonk_app depends_on: - db + volumes: + - ./config.toml:/listmonk/config.toml demo-db: + container_name: listmonk_demo_db <<: *db-defaults demo-app: <<: *app-defaults + container_name: listmonk_demo_app command: [sh, -c, "yes | ./listmonk --install --config config-demo.toml && ./listmonk --config config-demo.toml"] depends_on: - demo-db diff --git a/install-demo.sh b/install-demo.sh index 785d9f4..fbb6e7e 100755 --- a/install-demo.sh +++ b/install-demo.sh @@ -1,14 +1,10 @@ -#!/bin/sh - -set -e +#!/usr/bin/env sh +set -eu # Listmonk demo setup using `docker-compose`. -# # See https://listmonk.app/docs/installation/ for detailed installation steps. -# - -check_dependency() { +check_dependencies() { if ! command -v curl > /dev/null; then echo "curl is not installed." exit 1 @@ -35,6 +31,6 @@ show_output(){ } -check_dependency +check_dependencies setup_containers show_output diff --git a/install-prod.sh b/install-prod.sh new file mode 100644 index 0000000..397dffc --- /dev/null +++ b/install-prod.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env sh +set -eu + +# Listmonk production setup using `docker-compose`. +# See https://listmonk.app/docs/installation/ for detailed installation steps. + +printf '\n' + +RED="$(tput setaf 1 2>/dev/null || printf '')" +BLUE="$(tput setaf 4 2>/dev/null || printf '')" +GREEN="$(tput setaf 2 2>/dev/null || printf '')" +NO_COLOR="$(tput sgr0 2>/dev/null || printf '')" + +info() { + printf '%s\n' "${BLUE}>${NO_COLOR} $*" +} + +error() { + printf '%s\n' "${RED}x $*${NO_COLOR}" >&2 +} + +completed() { + printf '%s\n' "${GREEN}✓${GREEN} $*" +} + +exists() { + command -v "$1" 1>/dev/null 2>&1 +} + +check_dependencies() { + if ! exists curl; then + error "curl is not installed." + exit 1 + fi + + if ! exists docker; then + error "docker is not installed." + exit 1 + fi + + if ! exists docker-compose; then + error "docker-compose is not installed." + exit 1 + fi +} + +download() { + curl --fail --silent --location --output "$2" "$1" +} + +is_healthy() { + info "waiting for db container to be up. retrying in 3s" + health_status="$(docker inspect -f "{{.State.Health.Status}}" "$1")" + if [ "$health_status" = "healthy" ]; then + return 0 + else + return 1 + fi +} + +is_running() { + info "checking if "$1" is running" + status="$(docker inspect -f "{{.State.Status}}" "$1")" + if [ "$status" = "running" ]; then + return 0 + else + return 1 + fi +} + +generate_password(){ + echo $(tr -dc A-Za-z0-9