feat: Add easy install script

- Add a shell script to orchestrate a production setup with
`docker-compose`. The script fetches config and `docker-compose.yml`
from the `master` branch, generates a secure password, performs DB
migrations and starts the container services.

- Add a health check for Postgres container service in `docker-compose.yml`.

- Add cusotm `container_name` for services inside `docker-compose`.
This is helpful to check the status of containers in the install shell script.
This commit is contained in:
Karan Sharma 2021-06-14 19:20:13 +05:30
parent b3612927c8
commit 8d40422e0f
4 changed files with 174 additions and 10 deletions

View file

@ -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).

View file

@ -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

View file

@ -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

132
install-prod.sh Normal file
View file

@ -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 </dev/urandom | head -c 13 ; echo '')
}
get_config() {
info "fetching config.toml from listmonk repo"
download https://raw.githubusercontent.com/knadh/listmonk/master/config.toml.sample config.toml
}
get_containers() {
info "fetching docker-compose.yml from listmonk repo"
download https://raw.githubusercontent.com/knadh/listmonk/master/docker-compose.yml docker-compose.yml
}
modify_config(){
info "generating a random password"
db_password=$(generate_password)
info "modifying config.toml"
# Replace `db.host=localhost` with `db.host=db` in config file.
sed -i "s/host = \"localhost\"/host = \"listmonk_db\"/g" config.toml
# Replace `db.password=listmonk` with `db.password={{db_password}}` in config file.
# Note that `password` is wrapped with `\b`. This ensures that `admin_password` doesn't match this pattern instead.
sed -i "s/\bpassword\b = \"listmonk\"/password = \"$db_password\"/g" config.toml
# Replace `app.address=localhost:9000` with `app.address=0.0.0.0:9000` in config file.
sed -i "s/address = \"localhost:9000\"/address = \"0.0.0.0:9000\"/g" config.toml
info "modifying docker-compose.yml"
sed -i "s/POSTGRES_PASSWORD=listmonk/POSTGRES_PASSWORD=$db_password/g" docker-compose.yml
}
run_migrations(){
info "running migrations"
docker-compose up -d db
while ! is_healthy listmonk_db; do sleep 3; done
docker-compose run --rm app ./listmonk --install
}
start_services(){
info "starting app"
docker-compose up -d app db
}
show_output(){
info "finishing setup"
sleep 3
if is_running listmonk_db && is_running listmonk_app
then completed "Listmonk is now up and running. Visit http://localhost:9000 in your browser."
else
error "error running containers. something went wrong."
fi
}
check_dependencies
get_config
get_containers
modify_config
run_migrations
start_services
show_output