From 3329745650c99ae761c9ff49f4d1a8a3901d1c34 Mon Sep 17 00:00:00 2001 From: prichier Date: Mon, 19 Oct 2020 01:01:59 +0200 Subject: [PATCH] Add dockerfile and compose for production --- .gitlab-ci.yml | 123 --------------------------- Dockerfile | 11 +-- docker/production/Dockerfile | 62 ++++++++++++++ docker/production/README.md | 50 +++++++++++ docker/production/docker-compose.yml | 44 ++++++++++ docker/production/env | 10 +++ docker/production/prod.secret.exs | 49 +++++++++++ docker/production/start.sh | 3 + 8 files changed, 219 insertions(+), 133 deletions(-) delete mode 100644 .gitlab-ci.yml mode change 100644 => 120000 Dockerfile create mode 100644 docker/production/Dockerfile create mode 100644 docker/production/README.md create mode 100644 docker/production/docker-compose.yml create mode 100644 docker/production/env create mode 100644 docker/production/prod.secret.exs create mode 100755 docker/production/start.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 4a6efdf2f..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,123 +0,0 @@ -image: tcitworld/mobilizon-ci - -stages: - - check - - test - - deploy - -variables: - MIX_ENV: "test" - # DB Variables for Postgres / Postgis - POSTGRES_DB: mobilizon_test - POSTGRES_USER: postgres - POSTGRES_PASSWORD: "" - POSTGRES_HOST: postgres - # DB Variables for Mobilizon - MOBILIZON_DATABASE_USERNAME: $POSTGRES_USER - MOBILIZON_DATABASE_PASSWORD: $POSTGRES_PASSWORD - MOBILIZON_DATABASE_DBNAME: $POSTGRES_DB - MOBILIZON_DATABASE_HOST: $POSTGRES_HOST - GEOLITE_CITIES_PATH: "/usr/share/GeoIP/GeoLite2-City.mmdb" - MOBILIZON_INSTANCE_REGISTRATIONS_OPEN: "true" - -cache: - key: ${CI_COMMIT_REF_SLUG} - paths: - - ~/.cache/Cypress - - _build/ - - deps/ - - js/node_modules - - cache/Cypress - -lint: - stage: check - script: - - export EXITVALUE=0 - - mix deps.get - - mix credo --strict -a || export EXITVALUE=1 - - mix format --check-formatted --dry-run || export EXITVALUE=1 - - cd js - - yarn install - #- yarn run lint || export EXITVALUE=1 - - yarn run prettier --ignore-path="src/i18n/*" -c . || export EXITVALUE=1 - - yarn run build - - cd ../ - - exit $EXITVALUE - artifacts: - expire_in: 1 day - when: on_success - paths: - - priv/static - -deps: - stage: check - script: - - export EXITVALUE=0 - - mix deps.get - - mix hex.outdated || export EXITVALUE=1 - - cd js - - yarn outdated || export EXITVALUE=1 - - exit $EXITVALUE - allow_failure: true - -exunit: - stage: test - services: - - name: mdillon/postgis:11 - alias: postgres - before_script: - - cd js - - yarn install - - yarn run build - - cd ../ - - mix deps.get - - MIX_ENV=test mix ecto.create - - MIX_ENV=test mix ecto.migrate - dependencies: - - lint - script: - - mix coveralls -# cypress: -# stage: test -# services: -# - name: mdillon/postgis:11 -# alias: postgres -# script: -# - mix deps.get -# - cd js -# - yarn install -# - npx cypress install # just to be sure -# - yarn run build -# - cd ../ -# - MIX_ENV=e2e mix ecto.create -# - MIX_ENV=e2e mix ecto.migrate -# - MIX_ENV=e2e mix run priv/repo/e2e.seed.exs -# - MIX_ENV=e2e mix phx.server & -# - cd js -# - npx wait-on http://localhost:4000 -# - if [ -z "$CYPRESS_KEY" ]; then npx cypress run; else npx cypress run --record --parallel --key $CYPRESS_KEY; fi -# artifacts: -# expire_in: 2 day -# paths: -# - js/tests/e2e/screenshots/**/*.png -# - js/tests/e2e/videos/**/*.mp4 - -# pages: -# stage: deploy -# script: -# # - mkdir public -# # Mobilizon documentation is now on https://framagit.org/framasoft/joinmobilizon/documentation -# # Mix docs disabled because of https://github.com/elixir-lang/ex_doc/issues/1172 -# # - mix deps.get -# # - mix docs -# # - mv doc public/backend -# #- cd js -# #- yarn install -# #- yarn run styleguide:build -# #- mv styleguide ../public/frontend -# only: -# - master -# artifacts: -# expire_in: 1 hour -# paths: -# - public diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 9c73fff55..000000000 --- a/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM bitwalker/alpine-elixir:latest - -RUN apk add inotify-tools postgresql-client yarn file -RUN apk add --no-cache make gcc libc-dev argon2 imagemagick - -RUN mix local.hex --force && mix local.rebar --force - -WORKDIR /app - -EXPOSE 4000 diff --git a/Dockerfile b/Dockerfile new file mode 120000 index 000000000..27f3d3ac7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +./docker/production/Dockerfile \ No newline at end of file diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile new file mode 100644 index 000000000..259efd41d --- /dev/null +++ b/docker/production/Dockerfile @@ -0,0 +1,62 @@ +FROM elixir:slim + +# Install dependencies, NodeJS, YARN & clean apt +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 +RUN groupadd -r mobilizon \ + && useradd -r -g mobilizon -m mobilizon + +USER mobilizon + +# ENV +ENV MIX_ENV=prod + +# PORT +EXPOSE 4000 + +# Copy repo +COPY . /app +WORKDIR /app + +# Compile dependencies, Mobilizon and build front-end +RUN mix local.hex --force && mix local.rebar --force \ + && 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 diff --git a/docker/production/README.md b/docker/production/README.md new file mode 100644 index 000000000..6b9c9c87c --- /dev/null +++ b/docker/production/README.md @@ -0,0 +1,50 @@ +# Build and deploy Mobilizon with docker + +You will need to : +- build the image +- adapte env file +- run docker-compose + +## Build the image + + docker build -t mymobilizon -f docker/prod/Dockerfile . + +## Adapt env file + + cp env .env + +- Edit .env content with your params. +- 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: + + gpg --gen-random --armor 1 50 + +## run docker-compose + + docker-compose -f docker-compose-simple.yml up + # set user for volumes + sudo chown 999:999 db public wal public/upload + # in another shell + docker-compose -f docker-compose-simple.yml exec -u 0 mobilizon bash + su - mobilizon + # backup secret + mv config/prod.secret.exs config/prod.secret.exs.env + # run config generation + MIX_ENV=prod mix mobilizon.instance gen -f + # reply anything (not used after) except for : + # - What is the name of your database? [mobilizon_prod] + # - What is the user used to connect to your database? [mobilizon] + # - What is the password used to connect to your database? [autogenerated] + # get secret env based bak + mv config/prod.secret.exs.env config/prod.secret.exs + # run the db init script as root + exit + psql -U postgres -p 5432 -h postgres -f setup_db.psql + # delete db init sript + rm setup_db.psql + # create an admin with mobilizon user + su - mobilizon + cd /app + MIX_ENV=prod mix mobilizon.users.new pascoual@tedomum.fr --password mobilizon + # exit with ctrl+d (twice times) diff --git a/docker/production/docker-compose.yml b/docker/production/docker-compose.yml new file mode 100644 index 000000000..db38e50c9 --- /dev/null +++ b/docker/production/docker-compose.yml @@ -0,0 +1,44 @@ +version: "2.1" + +services: + mobilizon: + image: mobilizon + environment: + - MOBILIZON_INSTANCE_NAME="My Mobilizon Instance" + - MOBILIZON_INSTANCE_HOST=mobilizon.lan + - MOBILIZON_INSTANCE_EMAIL=noreply@mobilizon.lan + - MOBILIZON_INSTANCE_REGISTRATIONS_OPEN=true + - MOBILIZON_DATABASE_USERNAME + - MOBILIZON_DATABASE_PASSWORD + - MOBILIZON_DATABASE_DBNAME=mobilizon_prod + - MOBILIZON_DATABASE_HOST=postgres + - MOBILIZON_INSTANCE_SECRET_KEY_BASE + - MOBILIZON_INSTANCE_SECRET_KEY + - MOBILIZON_ADMIN_EMAIL=your@email.com + - MOBILIZON_SMPT_SERVER=yoursmtpserver + - MOBILIZON_SMPT_MOBILIZON_SMPT_HOSTNAME=your.smtp.domain + - MOBILIZON_SMPT_PORT=25 + - MOBILIZON_SMPT_USERNAME + - MOBILIZON_SMPT_PASSWORD + - MOBILIZON_SMPT_SSL=false + volumes: + - ./public/upload:/app/upload + ports: + - "4000:4000" + depends_on: + - postgres + + postgres: + image: postgis/postgis + volumes: + - ./db:/var/lib/postgresql/data + - ./wal:/wal + - ./postgresql.conf:/var/lib/postgresql/data/postgresql.conf + environment: + - POSTGRES_PASSWORD + - PGDATA=/var/lib/postgresql/data/pgdata + +networks: + default: + ipam: + driver: default diff --git a/docker/production/env b/docker/production/env new file mode 100644 index 000000000..e1a7972d9 --- /dev/null +++ b/docker/production/env @@ -0,0 +1,10 @@ +# You need to: +# cp env .env +# edite .env with your settings +MOBILIZON_DATABASE_PASSWORD=postgres +MOBILIZON_DATABASE_USERNAME=postgres +MOBILIZON_INSTANCE_SECRET_KEY_BASE=MmU1NWQyYWQtM2MzZC00ZTU5LTg0MmItMmY5NDZlMmNhNmEwCg +MOBILIZON_INSTANCE_SECRET_KEY=NjJhMGU5MDctZGNkOC00NGM0LWI5OWItZDEyY2FkNjRlODYyCg +MOBILIZON_SMPT_USERNAME=username +MOBILIZON_SMPT_PASSWORD=password +POSTGRES_PASSWORD=postgres \ No newline at end of file diff --git a/docker/production/prod.secret.exs b/docker/production/prod.secret.exs new file mode 100644 index 000000000..96cc31781 --- /dev/null +++ b/docker/production/prod.secret.exs @@ -0,0 +1,49 @@ +# Mobilizon instance configuration + +import Config + +config :mobilizon, Mobilizon.Web.Endpoint, + url: [host: System.get_env("MOBILIZON_INSTANCE_HOST", "mobilizon.lan")], + http: [port: 4000], + secret_key_base: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY_BASE", "ZcvexeC7cnwtKR8ADMBDwrYu2aYHUyjrOu4yA181Z112HNu/I5jyRleo4hoxOMqQ") + +config :mobilizon, Mobilizon.Web.Auth.Guardian, + secret_key: System.get_env("MOBILIZON_INSTANCE_SECRET_KEY", "KsdUIvp6hQ7b97yxUZcDQyGH0g4LS3fF0OvIsIATpkKzd1MDvSS4KexWXsjXeMQZ") + +config :mobilizon, :instance, + name: System.get_env("MOBILIZON_INSTANCE_NAME", "Mobilizon"), + description: "Change this to a proper description of your instance", + hostname: System.get_env("MOBILIZON_INSTANCE_HOST", "mobilizon.lan"), + registrations_open: System.get_env("MOBILIZON_INSTANCE_REGISTRATIONS_OPEN", "false"), + demo: false, + allow_relay: true, + federating: true, + email_from: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan"), + email_reply_to: System.get_env("MOBILIZON_INSTANCE_EMAIL", "noreply@mobilizon.lan") + +config :mobilizon, Mobilizon.Storage.Repo, + adapter: Ecto.Adapters.Postgres, + username: System.get_env("MOBILIZON_DATABASE_USERNAME", "username"), + password: System.get_env("MOBILIZON_DATABASE_PASSWORD", "password"), + database: System.get_env("MOBILIZON_DATABASE_DBNAME", "mobilizon"), + hostname: System.get_env("MOBILIZON_DATABASE_HOST", "postgres"), + port: "5432", + pool_size: 10 + +config :mobilizon, Mobilizon.Web.Email.Mailer, + adapter: Bamboo.SMTPAdapter, + server: System.get_env("MOBILIZON_SMPT_SERVER", "localhost"), + hostname: System.get_env("MOBILIZON_SMPT_HOSTNAME", "localhost"), + port: System.get_env("MOBILIZON_SMPT_PORT", "25"), + username: System.get_env("MOBILIZON_SMPT_USERNAME", nil), + password: System.get_env("MOBILIZON_SMPT_PASSWORD", nil), + # can be `:always` or `:never` + tls: :if_available, + allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"], + # can be `true` + ssl: System.get_env("MOBILIZON_SMPT_SSL", "false"), + retries: 1, + # can be `true` + no_mx_lookups: false, + # can be `:always`. If your smtp relay requires authentication set it to `:always`. + auth: :if_available diff --git a/docker/production/start.sh b/docker/production/start.sh new file mode 100755 index 000000000..25b32dd12 --- /dev/null +++ b/docker/production/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash +mix ecto.migrate +mix phx.server \ No newline at end of file