Deploying an Elixir Release using Docker on DigitalOcean
Tags: docker, digitalocean, elixir, deployment
Published: 2021-10-18 10:02:30

---
title: Deploying an Elixir Release using Docker on DigitalOcean 
published: true
description: How to deploy an Elixir Release using Docker on DigitalOcean
tags: docker, digitalocean, elixir, deployment
//cover_image: https://direct_url_to_image.jpg
canonical_url: https://blog.miguelcoba.com/deploying-an-elixir-release-using-docker-on-digitalocean
series: Deploying Elixir
---

Last time [we created a Docker image](https://blog.miguelcoba.com/deploying-a-phoenix-16-app-with-docker-and-elixir-releases) and ran a container based on it. Now we'll deploy our Elixir Release Docker image in DigitalOcean.

There are several approaches to this:

* Let DigitalOcean access directly your GitHub or GitLab repository
* Put the image in Docker public registry where DigitalOcean can fetch it
* Put the image in DigitalOcean own Container Registry

In this article we'll use the first approach 

## Create a repository

I'll show how to do it in GitHub but should be similarly easy in GitLab

### GitHub

Create a new repository

![Create new repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5uy0l67q6ngg1g0mor6s.png)

push the code:

```bash
git remote add origin git@github.com:miguelcoba/saturn.git
git branch -M main
git push -u origin main
```

### Prepare to deploy to DigitalOcean

DigitalOcean requires some changes to our code in order to correctly connect to the DB from our Docker application.

So far we have been establishing a plain, unencrypted connections between the application and the database. This won't work for DigitalOcean as they strictly enforce SSL when connecting to the database.

In our case, that means that we need to enable SSL on the application side every time we open a connection to the database.

First thing is to configure the Repo to use ssl. Open `runtime.ex` and uncomment the `ssl: true` line on the `Repo` section:

```elixir
  config :saturn, Saturn.Repo,
    ssl: true,
    # socket_options: [:inet6],
    url: database_url,
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
```

This will enable SSL for all the connections in the pool that the repository uses to connect to the database.

We need to change the `Saturn.Release` module that we use to run the migrations, because that also opens a connection to the database and we need it to start the `ssl` application at the beginning.

Change the `load_app` function in the `Saturn.Release` module to be like this:

```elixir
  defp load_app do
    Application.ensure_all_started(:ssl)
    Application.load(@app)
  end
```

This will ensure the ssl application is started before trying to connect to the database to run the migrations.

We need to commit this changes to the repository. DigitalOcean works by deploying a specific branch from our repository and building the Docker image with what it finds in that branch. If you plan to use Docker as your production environment then is fine to commit this to the main branch and setup DigitalOcean to use the main branch for deployment.
For this example, I will use a different branch to commit these changes and configure DigitalOcean to use that branch. I'll use a branch named `digital-ocean-deployment`

```bash
git checkout -b digital-ocean-deployment
git add .
git commit -m "Setup for deploying to DigitalOcean"
git push -u origin digital-ocean-deployment
```

## Creating an App in DigitalOcean

Let's do the deployment to DigitalOcean.

Go to your DigitalOcean dashboard and create a new App:

![Create New App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ow946bi2d3gm1tjuvy0a.png)
 
Select GitHub on the "Choose Source" screen:

![Choose GitHub as a source](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mk43vltqe2a1ficafyji.png)

The first time you do this, GitHub will require you to authorize DigitalOcean to access your repositories. Follow the instructions and give access to the repository you just created

![Authorize DigitalOcean](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5mv9pf3up7gsf15fl48c.png)

![Authorization granted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7photri7tku8fw4cfliq.png)

You'll get back to the "Choose source" and you'll see the list of authorized repositories there

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hol6wb4q5048aj6qcgw4.png)

Select your repository and you'll see that the `main` branch is selected automatically

![Repository selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fh5ucjauljbc93ndpl0s.png)

If you're using `main` that's fine. For this article, I'll change it to the `digital-ocean-deployment` branch:

![Branch selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kptcvj3e1guhz05bw1xd.png)

Click Next to move to the "Configure your app" page:

![Configure app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p0mb007cbxrldeyca8sc.png)

We need to configure the environment variables that DigitalOcean will provide to our Docker container in runtime. We can omit the `PORT` environment variable as DigitalOcean automatically provides it. We have to create the `POOL_SIZE`, `DATABASE_URL`, and `SECRET_KEY_BASE`. Let's start with the last one. 

Click on the Edit link in the "Environment Variables" section. Then, in a terminal execute this command:

```bash
mix phx.gen.secret
```

Add a variable named SECRET_KEY_BASE and put the value you got from the command in it. Check the "Encrypt" option.

![SECRET_KEY_BASE environment variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c3vycrt7ao2eg8w0o60.png)

Now create a `POOL_SIZE` with value 2 and a DATABASE_URL with value `${db.DATABASE_URL}`. These two don't need to be encrypted.

![Environment variables](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no3edzhlly56ak0aasib.png)

We need to create a database. Click on the "Add a Database" button:

![Add a Database](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckx09yn10sk51bpuwlii.png)

Accept the default values for the database and now you're ready to create the App in DigitalOcean.

One thing to note: the DATABASE_URL environment variable is referring to this database we just created. It will be replaced with the correct value to connect to this database when the application starts. 

Click next to proceed to the "Name your web service" page:

![Name your web service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mo1x24oygrynzmz9rjyd.png)

Accept the defaults and click Next. You're now in the "Finalize and launch" page:

![Finalize and launch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u41zk6rgpq48rzsni80t.png)

Click the "Launch Basic App" and you'll see your app being created.

![App creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6mbmcz5ptcxoiirvg86.png)

DigitalOcean will now:

1. Access your repository
2. Clone it,
3. Detect the `Dockerfile` in it
4. Build a Docker image from it
5. Push it to their own Container Registry
6. Provision the database
7. Set up environment variables
8. Provision a server to run the Docker container
9. Run the application

You can check the progress by inspecting the logs:

![Realtime logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jjhkgnn9okgi093afqmx.png)

At the end you'll have your app deployed:

![Deployment successful](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a181y8luyj8zy7q8065r.png)

## Run the migrations

You can access the elixir container console and run the migrations. Go to the "Console" tab and there evaluate the following command:

```bash
bin/saturn eval "Saturn.Release.migrate"
```

You'll see something like this:

![Run DB migrations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d26yrhf05vwqjj767qbm.png)

Finally, visit the application by clicking the "Live App" button:

![Live App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o334rl97jo1slhu26zvx.png)

You'll see your app running in DigitalOcean's infrastructure:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbn2gc4egauhv6ebh4ml.png)

We are done!

## Source code

The  [source code](https://github.com/miguelcoba/saturn/tree/digital-ocean-deployment)  for the saturn project is open source under the MIT license. Use the `digital-ocean-deployment` branch.

## About

I'm [Miguel Cobá](https://miguelcoba.com). I write about Elixir, Elm, Software Development, and eBook writing.

- Follow me on [Twitter](https://twitter.com/MiguelCoba_)
- Subscribe to my [newsletter](https://newsletter.miguelcoba.com)
- Read all my articles on my [blog](https://blog.miguelcoba.com)
- Get my books:
    - [100 Elixir Tips](https://store.miguelcoba.com/l/100elixirtips) [FREE]
    - [Deploying Elixir](https://store.miguelcoba.com/l/deployingelixir) [FREE]
    - [Deploying Elixir: Advanced Topics](https://store.miguelcoba.com/l/advancedtopics)
    - [eBook Writing Workflow for Developers](https://store.miguelcoba.com/l/ebookwriting)