Let's pretend our life depends on transmitting as much tutorial as possible in the least time. Okay, let's kick things off.
If you're using Phoenix, you don't have to write one. It generates a masterfully-written Dockerfile for you.
mix phx.gen.release --docker
It's one of the best ones I've ever seen. It's production ready and works with Mix releases.
Since we're not doing a multi-host or crazy deployment, Docker Compose is an excellent solution for raising the app quickly.
version: "3.8" services: web: build: . ports: - "4000:4000" environment: - SECRET_KEY_BASE=secret-key - DATABASE_URL=postgres://postgres:matteing-is-awesome@postgres:5432/postgres deploy: restart_policy: condition: on-failure delay: 5s max_attempts: 3 depends_on: - postgres postgres: image: postgres restart: always user: postgres ports: - "5432:5432" environment: POSTGRES_PASSWORD: matteing-is-awesome healthcheck: test: ["CMD-SHELL", "pg_isready"] interval: 1s timeout: 5s retries: 10
Change the configuration for anything that seems weird, and fill in your environment settings. I've taken the Postgres bits from their official documentation.
git clone git@github.com:matteing/app.git sudo docker compose up -d
Note we used the -d
flag--this tells Docker to run in detached mode, so the containers keep running in the background, following the restart policy.
Tail the logs and check that deployment out! Nothing works the first time, so fix it and repeat.
sudo docker compose logs -f
Most likely, the first error you're going to get is a database error. You probably haven't run migrations yet.
sudo docker exec -it <app>-web-1 /app/bin/migrate
After you've changed things in your app code, you've gotta rebuild the images and tell compose to restart the changed containers.
sudo docker compose up --build -d
This is a good introduction to a common maintenance item, which is executing one-off commands or entering the iex
console.
You interact with your app through a single binary, <appname>
--in my case, athena
. Here's all you can do with it.
sudo docker exec -it athena-web-1 /app/bin/athena
Usage: athena COMMAND [ARGS] The known commands are: start Starts the system start_iex Starts the system with IEx attached daemon Starts the system as a daemon daemon_iex Starts the system as a daemon with IEx attached eval "EXPR" Executes the given expression on a new, non-booted system rpc "EXPR" Executes the given expression remotely on the running system remote Connects to the running system via a remote shell restart Restarts the running system via a remote command stop Stops the running system via a remote command pid Prints the operating system PID of the running system via a remote command version Prints the release name and version to be booted
To start a shell:
sudo docker exec -it athena-web-1 /app/bin/athena remote # => iex(athena@0963c349efc1)1>
A reader and good friend Giovanni Collazo noted that all the commands above include sudo
. Adding yourself to the docker
group in the system will allow you to overcome this limitation.
sudo groupadd docker sudo gpasswd -a $USER docker # refresh! newgrp docker
If you're doing a production deployment, place a reverse proxy in front of the app, like Nginx, Caddy or Traefik. I am running my services in a local server at the moment, so it's not necessary for me, but for a production setup it's a must.
My favorite option is Caddy. Note that it's important to include the volumes section in the Docker compose--otherwise, Caddy will regenerate all certs on every boot.
The quickest and dirtiest guide to going from "zero" to "almost production ready" in an hour.
If you're going public, go through your compose file, harden the instance, and expose.
Enjoy your Elixirist days.