Mutli-stage build for production

This commit is contained in:
prichier 2020-10-22 15:19:01 +02:00
parent e945f48665
commit 1acff2dd8a
8 changed files with 167 additions and 172 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +0,0 @@
#!/bin/bash
mix ecto.migrate
mix phx.server

11
lib/mobilizon/cli.ex Normal file
View 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