Mutli-stage build for production
This commit is contained in:
parent
e945f48665
commit
1acff2dd8a
|
@ -1,45 +1,39 @@
|
||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
mobilizon:
|
||||||
container_name: mobilizon_db
|
image: mobilizon
|
||||||
restart: unless-stopped
|
|
||||||
image: mdillon/postgis:11
|
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: postgres
|
- MOBILIZON_INSTANCE_NAME
|
||||||
POSTGRES_DB: mobilizon_dev
|
- MOBILIZON_INSTANCE_HOST
|
||||||
|
- MOBILIZON_INSTANCE_EMAIL
|
||||||
|
- MOBILIZON_REPLY_EMAIL
|
||||||
|
- MOBILIZON_INSTANCE_REGISTRATIONS_OPEN=true
|
||||||
|
- MOBILIZON_DATABASE_USERNAME=${POSTGRES_USER}
|
||||||
|
- MOBILIZON_DATABASE_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
- MOBILIZON_DATABASE_DBNAME=${POSTGRES_DB}
|
||||||
|
- MOBILIZON_DATABASE_HOST=db
|
||||||
|
- MOBILIZON_INSTANCE_SECRET_KEY_BASE
|
||||||
|
- MOBILIZON_INSTANCE_SECRET_KEY
|
||||||
|
- MOBILIZON_SMTP_SERVER=yoursmtpserver
|
||||||
|
- MOBILIZON_SMTP_HOSTNAME=your.smtp.domain
|
||||||
|
- MOBILIZON_SMTP_USERNAME
|
||||||
|
- MOBILIZON_SMTP_PASSWORD
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- /tmp/public/upload:/app/upload
|
||||||
api:
|
|
||||||
container_name: mobilizon_api
|
|
||||||
restart: unless-stopped
|
|
||||||
build: .
|
|
||||||
volumes:
|
|
||||||
- '.:/app'
|
|
||||||
ports:
|
ports:
|
||||||
- "4000:4000"
|
- "4000:4000"
|
||||||
depends_on:
|
|
||||||
- postgres
|
db:
|
||||||
|
image: postgis/postgis
|
||||||
|
volumes:
|
||||||
|
- /tmp/db:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
MIX_ENV: "dev"
|
- POSTGRES_USER
|
||||||
DOCKER: "true"
|
- POSTGRES_PASSWORD
|
||||||
MOBILIZON_INSTANCE_NAME: My Mobilizon Instance
|
- POSTGRES_DB
|
||||||
MOBILIZON_INSTANCE_HOST: mobilizon.me
|
|
||||||
MOBILIZON_INSTANCE_EMAIL: noreply@mobilizon.me
|
networks:
|
||||||
MOBILIZON_INSTANCE_REGISTRATIONS_OPEN: "true"
|
default:
|
||||||
MOBILIZON_DATABASE_PASSWORD: postgres
|
ipam:
|
||||||
MOBILIZON_DATABASE_USERNAME: postgres
|
driver: default
|
||||||
MOBILIZON_DATABASE_DBNAME: mobilizon_dev
|
|
||||||
MOBILIZON_DATABASE_HOST: postgres
|
|
||||||
command: >
|
|
||||||
sh -c "cd js &&
|
|
||||||
yarn install &&
|
|
||||||
cd ../ &&
|
|
||||||
mix deps.get &&
|
|
||||||
mix compile &&
|
|
||||||
mix ecto.create &&
|
|
||||||
mix ecto.migrate &&
|
|
||||||
mix phx.server"
|
|
||||||
volumes:
|
|
||||||
pgdata:
|
|
||||||
.:
|
|
||||||
|
|
|
@ -1,62 +1,41 @@
|
||||||
FROM elixir:slim
|
# First build the application assets
|
||||||
|
FROM node:alpine as assets
|
||||||
|
|
||||||
# Install dependencies, NodeJS, YARN & clean apt
|
RUN apk add --no-cache python build-base
|
||||||
RUN apt update \
|
|
||||||
&& apt -y dist-upgrade \
|
|
||||||
&& apt -y install build-essential \
|
|
||||||
curl \
|
|
||||||
wget \
|
|
||||||
unzip \
|
|
||||||
vim \
|
|
||||||
openssl \
|
|
||||||
git \
|
|
||||||
cmake \
|
|
||||||
imagemagick \
|
|
||||||
webp \
|
|
||||||
gifsicle \
|
|
||||||
jpegoptim \
|
|
||||||
optipng \
|
|
||||||
pngquant \
|
|
||||||
postgresql-client \
|
|
||||||
&& curl -sL https://deb.nodesource.com/setup_12.x | bash - \
|
|
||||||
&& apt -y install nodejs \
|
|
||||||
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
|
|
||||||
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
|
|
||||||
&& apt -y update && apt -y install yarn \
|
|
||||||
&& apt -y clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
|
||||||
|
|
||||||
# Add mobilizon user
|
COPY js .
|
||||||
RUN groupadd -r mobilizon \
|
RUN yarn install \
|
||||||
&& useradd -r -g mobilizon -m mobilizon
|
&& yarn run build
|
||||||
|
|
||||||
USER mobilizon
|
# Then, build the application binary
|
||||||
|
FROM elixir:alpine AS builder
|
||||||
|
|
||||||
# ENV
|
RUN apk add --no-cache build-base git cmake
|
||||||
|
|
||||||
|
COPY mix.exs mix.lock ./
|
||||||
ENV MIX_ENV=prod
|
ENV MIX_ENV=prod
|
||||||
|
RUN mix local.hex --force \
|
||||||
|
&& mix local.rebar --force \
|
||||||
|
&& mix deps.get
|
||||||
|
|
||||||
# PORT
|
COPY lib ./lib
|
||||||
|
COPY priv ./priv
|
||||||
|
COPY config ./config
|
||||||
|
COPY docker/production/releases.exs ./config/
|
||||||
|
COPY --from=assets ./priv/static ./priv/static
|
||||||
|
|
||||||
|
RUN mix phx.digest \
|
||||||
|
&& mix release
|
||||||
|
|
||||||
|
# Finally setup the app
|
||||||
|
FROM alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache openssl ncurses-libs
|
||||||
|
|
||||||
|
USER nobody
|
||||||
EXPOSE 4000
|
EXPOSE 4000
|
||||||
|
|
||||||
# Copy repo
|
COPY --from=builder --chown=nobody:nobody _build/prod/rel/mobilizon ./
|
||||||
COPY . /app
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Compile dependencies, Mobilizon and build front-end
|
ENTRYPOINT ["/bin/mobilizon"]
|
||||||
RUN mix local.hex --force && mix local.rebar --force \
|
CMD ["start"]
|
||||||
&& HEX_HTTP_CONCURRENCY=4 HEX_HTTP_TIMEOUT=60 mix do deps.get, compile \
|
|
||||||
&& cd js && NODE_BUILD_MEMORY=2024 yarn install && NODE_BUILD_MEMORY=2024 yarn run build \
|
|
||||||
# free space
|
|
||||||
&& rm -rf js doc deps docs support \
|
|
||||||
&& rm -rf /home/mobilizon/.cache/* \
|
|
||||||
# copy config secret env based file
|
|
||||||
&& cp docker/production/prod.secret config/ \
|
|
||||||
# set start script mod
|
|
||||||
&& chmod +x /app/docker/production/start.sh
|
|
||||||
|
|
||||||
CMD /app/docker/production/start.sh
|
|
||||||
|
|
||||||
## start.sh:
|
|
||||||
# !/bin/bash
|
|
||||||
# mix ecto.migrate
|
|
||||||
# mix phx.server
|
|
||||||
|
|
|
@ -2,49 +2,54 @@
|
||||||
|
|
||||||
You will need to :
|
You will need to :
|
||||||
- build the image
|
- build the image
|
||||||
- adapte env file
|
- tune the environment file
|
||||||
- run docker-compose
|
- use docker-compose to run the service
|
||||||
|
|
||||||
## Build the image
|
## Build the image
|
||||||
|
|
||||||
docker build -t mymobilizon -f docker/prod/Dockerfile .
|
git clone https://forge.tedomum.net/tedomum/mobilizon
|
||||||
|
cd mobilizon
|
||||||
|
docker build -t mobilizon -f docker/production/Dockerfile .
|
||||||
|
|
||||||
## Adapt env file
|
## Update the env file
|
||||||
|
|
||||||
cp env .env
|
cd docker/production/
|
||||||
|
cp env.example .env
|
||||||
|
|
||||||
- Edit .env content with your params.
|
Edit the `.env` content with your own settings.
|
||||||
- Edit docker-compose file with your params (environment section for mobilizon & posgres).
|
|
||||||
|
|
||||||
You can generate `MOBILIZON_INSTANCE_SECRET_KEY_BASE` and `MOBILIZON_INSTANCE_SECRET_KEY` with:
|
You can generate `MOBILIZON_INSTANCE_SECRET_KEY_BASE` and `MOBILIZON_INSTANCE_SECRET_KEY` with:
|
||||||
|
|
||||||
gpg --gen-random --armor 1 50
|
gpg --gen-random --armor 1 50
|
||||||
|
|
||||||
## run docker-compose
|
## Run the service
|
||||||
|
|
||||||
docker-compose -f docker-compose-simple.yml up
|
Start by initializing and running the database:
|
||||||
# set user for volumes
|
|
||||||
sudo chown 999:999 db public wal public/upload
|
docker-compose up -d db
|
||||||
# in another shell
|
|
||||||
docker-compose -f docker-compose-simple.yml exec -u 0 mobilizon bash
|
Instanciate required Postgres extensions:
|
||||||
su - mobilizon
|
|
||||||
# backup secret
|
docker-compose exec db psql -U <username>
|
||||||
mv config/prod.secret.exs config/prod.secret.exs.env
|
# CREATE EXTENSION pg_trgm;
|
||||||
# run config generation
|
# CREATE EXTENSION unaccent;
|
||||||
MIX_ENV=prod mix mobilizon.instance gen -f
|
|
||||||
# reply anything (not used after) except for :
|
|
||||||
# - What is the name of your database? [mobilizon_prod]
|
Then run migrations:
|
||||||
# - What is the user used to connect to your database? [mobilizon]
|
|
||||||
# - What is the password used to connect to your database? [autogenerated]
|
docker-compose run --rm mobilizon eval Mobilizon.Cli.migrate
|
||||||
# get secret env based bak
|
|
||||||
mv config/prod.secret.exs.env config/prod.secret.exs
|
Finally, run the application:
|
||||||
# run the db init script as root
|
|
||||||
exit
|
docker-compose up -d mobilizon
|
||||||
psql -U postgres -p 5432 -h postgres -f setup_db.psql
|
|
||||||
# delete db init sript
|
## Update the service
|
||||||
rm setup_db.psql
|
|
||||||
# create an admin with mobilizon user
|
Pull the latest image, then run the migrations:
|
||||||
su - mobilizon
|
|
||||||
cd /app
|
docker-compose pull mobilizon
|
||||||
MIX_ENV=prod mix mobilizon.users.new pascoual@tedomum.fr --password mobilizon
|
docker-compose run --rm mobilizon eval Mobilizon.Cli.migrate
|
||||||
# exit with ctrl+d (twice times)
|
|
||||||
|
Finally, update the service:
|
||||||
|
|
||||||
|
docker-compose up -d mobilizon
|
||||||
|
|
|
@ -1,42 +1,37 @@
|
||||||
version: "2.1"
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mobilizon:
|
mobilizon:
|
||||||
image: mobilizon
|
image: mobilizon
|
||||||
environment:
|
environment:
|
||||||
- MOBILIZON_INSTANCE_NAME="My Mobilizon Instance"
|
- MOBILIZON_INSTANCE_NAME
|
||||||
- MOBILIZON_INSTANCE_HOST=mobilizon.lan
|
- MOBILIZON_INSTANCE_HOST
|
||||||
- MOBILIZON_INSTANCE_EMAIL=noreply@mobilizon.lan
|
- MOBILIZON_INSTANCE_EMAIL
|
||||||
|
- MOBILIZON_REPLY_EMAIL
|
||||||
- MOBILIZON_INSTANCE_REGISTRATIONS_OPEN=true
|
- MOBILIZON_INSTANCE_REGISTRATIONS_OPEN=true
|
||||||
- MOBILIZON_DATABASE_USERNAME
|
- MOBILIZON_DATABASE_USERNAME=${POSTGRES_USER}
|
||||||
- MOBILIZON_DATABASE_PASSWORD
|
- MOBILIZON_DATABASE_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
- MOBILIZON_DATABASE_DBNAME=mobilizon_prod
|
- MOBILIZON_DATABASE_DBNAME=${POSTGRES_DB}
|
||||||
- MOBILIZON_DATABASE_HOST=postgres
|
- MOBILIZON_DATABASE_HOST=db
|
||||||
- MOBILIZON_INSTANCE_SECRET_KEY_BASE
|
- MOBILIZON_INSTANCE_SECRET_KEY_BASE
|
||||||
- MOBILIZON_INSTANCE_SECRET_KEY
|
- MOBILIZON_INSTANCE_SECRET_KEY
|
||||||
- MOBILIZON_ADMIN_EMAIL=your@email.com
|
- MOBILIZON_SMTP_SERVER=yoursmtpserver
|
||||||
- MOBILIZON_SMPT_SERVER=yoursmtpserver
|
- MOBILIZON_SMTP_HOSTNAME=your.smtp.domain
|
||||||
- MOBILIZON_SMPT_MOBILIZON_SMPT_HOSTNAME=your.smtp.domain
|
- MOBILIZON_SMTP_USERNAME
|
||||||
- MOBILIZON_SMPT_PORT=25
|
- MOBILIZON_SMTP_PASSWORD
|
||||||
- MOBILIZON_SMPT_USERNAME
|
|
||||||
- MOBILIZON_SMPT_PASSWORD
|
|
||||||
- MOBILIZON_SMPT_SSL=false
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./public/upload:/app/upload
|
- ./public/upload:/app/upload
|
||||||
ports:
|
ports:
|
||||||
- "4000:4000"
|
- "4000:4000"
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
|
|
||||||
postgres:
|
db:
|
||||||
image: postgis/postgis
|
image: postgis/postgis
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/var/lib/postgresql/data
|
- ./db:/var/lib/postgresql/data
|
||||||
- ./wal:/wal
|
|
||||||
- ./postgresql.conf:/var/lib/postgresql/data/postgresql.conf
|
|
||||||
environment:
|
environment:
|
||||||
|
- POSTGRES_USER
|
||||||
- POSTGRES_PASSWORD
|
- POSTGRES_PASSWORD
|
||||||
- PGDATA=/var/lib/postgresql/data/pgdata
|
- POSTGRES_DB
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,10 +1,27 @@
|
||||||
# You need to:
|
# Copy this file to env, then update it with your own settings
|
||||||
# cp env .env
|
|
||||||
# edite .env with your settings
|
# Database settings
|
||||||
MOBILIZON_DATABASE_PASSWORD=postgres
|
POSTGRES_USER=mobilizon
|
||||||
MOBILIZON_DATABASE_USERNAME=postgres
|
POSTGRES_PASSWORD=changethis
|
||||||
MOBILIZON_INSTANCE_SECRET_KEY_BASE=MmU1NWQyYWQtM2MzZC00ZTU5LTg0MmItMmY5NDZlMmNhNmEwCg
|
POSTGRES_DB=mobilizon
|
||||||
MOBILIZON_INSTANCE_SECRET_KEY=NjJhMGU5MDctZGNkOC00NGM0LWI5OWItZDEyY2FkNjRlODYyCg
|
|
||||||
MOBILIZON_SMPT_USERNAME=username
|
# Application config
|
||||||
|
MOBILIZON_INSTANCE_SECRET_KEY_BASE=changethis
|
||||||
|
MOBILIZON_INSTANCE_SECRET_KEY=changethis
|
||||||
|
MOBILIZON_SMTP_USERNAME=username
|
||||||
|
MOBILIZON_SMPT_PASSWORD=password
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
|
||||||
|
# Instance configuration
|
||||||
|
MOBILIZON_INSTANCE_NAME=My Mobilizon Instance
|
||||||
|
MOBILIZON_INSTANCE_HOST=mobilizon.lan
|
||||||
|
MOBILIZON_INSTANCE_SECRET_KEY_BASE=changethis
|
||||||
|
MOBILIZON_INSTANCE_SECRET_KEY=changethis
|
||||||
|
MOBILIZON_INSTANCE_EMAIL=noreply@mobilizon.lan
|
||||||
|
MOBILIZON_REPLY_EMAIL=contact@mobilizon.lan
|
||||||
|
|
||||||
|
# Email settings
|
||||||
|
MOBILIZON_SMPT_SERVER=localhost
|
||||||
|
MOBILIZON_SMPT_HOSTNAME=localhost
|
||||||
|
MOBILIZON_SMPT_USERNAME=noreply@mobilizon.lan
|
||||||
MOBILIZON_SMPT_PASSWORD=password
|
MOBILIZON_SMPT_PASSWORD=password
|
||||||
POSTGRES_PASSWORD=postgres
|
|
|
@ -3,12 +3,13 @@
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
config :mobilizon, Mobilizon.Web.Endpoint,
|
config :mobilizon, Mobilizon.Web.Endpoint,
|
||||||
|
server: true,
|
||||||
url: [host: System.get_env("MOBILIZON_INSTANCE_HOST", "mobilizon.lan")],
|
url: [host: System.get_env("MOBILIZON_INSTANCE_HOST", "mobilizon.lan")],
|
||||||
http: [port: 4000],
|
http: [port: 4000],
|
||||||
secret_key_base: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY_BASE", "ZcvexeC7cnwtKR8ADMBDwrYu2aYHUyjrOu4yA181Z112HNu/I5jyRleo4hoxOMqQ")
|
secret_key_base: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY_BASE", "changethis")
|
||||||
|
|
||||||
config :mobilizon, Mobilizon.Web.Auth.Guardian,
|
config :mobilizon, Mobilizon.Web.Auth.Guardian,
|
||||||
secret_key: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY", "KsdUIvp6hQ7b97yxUZcDQyGH0g4LS3fF0OvIsIATpkKzd1MDvSS4KexWXsjXeMQZ")
|
secret_key: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY", "changethis")
|
||||||
|
|
||||||
config :mobilizon, :instance,
|
config :mobilizon, :instance,
|
||||||
name: System.get_env("MOBILIZON_INSTANCE_NAME", "Mobilizon"),
|
name: System.get_env("MOBILIZON_INSTANCE_NAME", "Mobilizon"),
|
||||||
|
@ -19,7 +20,7 @@ config :mobilizon, :instance,
|
||||||
allow_relay: true,
|
allow_relay: true,
|
||||||
federating: true,
|
federating: true,
|
||||||
email_from: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan"),
|
email_from: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan"),
|
||||||
email_reply_to: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan")
|
email_reply_to: System.get_env("MOBILIZON_REPLY_EMAIL", "noreply@mobilizon.lan")
|
||||||
|
|
||||||
config :mobilizon, Mobilizon.Storage.Repo,
|
config :mobilizon, Mobilizon.Storage.Repo,
|
||||||
adapter: Ecto.Adapters.Postgres,
|
adapter: Ecto.Adapters.Postgres,
|
||||||
|
@ -32,18 +33,14 @@ config :mobilizon, Mobilizon.Storage.Repo,
|
||||||
|
|
||||||
config :mobilizon, Mobilizon.Web.Email.Mailer,
|
config :mobilizon, Mobilizon.Web.Email.Mailer,
|
||||||
adapter: Bamboo.SMTPAdapter,
|
adapter: Bamboo.SMTPAdapter,
|
||||||
server: System.get_env("MOBILIZON_SMPT_SERVER", "localhost"),
|
server: System.get_env("MOBILIZON_SMTP_SERVER", "localhost"),
|
||||||
hostname: System.get_env("MOBILIZON_SMPT_HOSTNAME", "localhost"),
|
hostname: System.get_env("MOBILIZON_SMTP_HOSTNAME", "localhost"),
|
||||||
port: System.get_env("MOBILIZON_SMPT_PORT", "25"),
|
port: System.get_env("MOBILIZON_SMTP_PORT", "25"),
|
||||||
username: System.get_env("MOBILIZON_SMPT_USERNAME", nil),
|
username: System.get_env("MOBILIZON_SMTP_USERNAME", nil),
|
||||||
password: System.get_env("MOBILIZON_SMPT_PASSWORD", nil),
|
password: System.get_env("MOBILIZON_SMTP_PASSWORD", nil),
|
||||||
# can be `:always` or `:never`
|
|
||||||
tls: :if_available,
|
tls: :if_available,
|
||||||
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
|
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
|
||||||
# can be `true`
|
ssl: System.get_env("MOBILIZON_SMTP_SSL", "false"),
|
||||||
ssl: System.get_env("MOBILIZON_SMPT_SSL", "false"),
|
|
||||||
retries: 1,
|
retries: 1,
|
||||||
# can be `true`
|
|
||||||
no_mx_lookups: false,
|
no_mx_lookups: false,
|
||||||
# can be `:always`. If your smtp relay requires authentication set it to `:always`.
|
|
||||||
auth: :if_available
|
auth: :if_available
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
mix ecto.migrate
|
|
||||||
mix phx.server
|
|
11
lib/mobilizon/cli.ex
Normal file
11
lib/mobilizon/cli.ex
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
defmodule Mobilizon.Cli do
|
||||||
|
@app :mobilizon
|
||||||
|
|
||||||
|
def migrate do
|
||||||
|
Application.load(@app)
|
||||||
|
|
||||||
|
for repo <- Application.fetch_env!(@app, :ecto_repos) do
|
||||||
|
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue