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:
parent
b3612927c8
commit
8d40422e0f
4 changed files with 174 additions and 10 deletions
29
README.md
29
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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
132
install-prod.sh
Normal 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
|
Loading…
Reference in a new issue