Deploying Server-Side Swift Apps With Docker on Heroku

In this tutorial, you’ll learn how to deploy server-side applications developed in Vapor as well as Docker images of your application into Heroku. By Natan Rolnik.

4.5 (2) · 1 Review

Download materials
Save for later

For months, you’ve worked hard on building an API for your app. Now, you want to make it available over the internet. You’re not quite sure what the best option is — or even where to start. Rest assured, this tutorial shows the step-by-step instructions to deploy Server-Side Swift apps with Docker on Heroku.

Most developers with Swift experience come from an iOS or macOS development background, and deploying web apps might not be a trivial task for you. Managing servers, ensuring zero downtime, scaling servers or dealing with other DevOps-related tasks are all hard work. Recognizing this opportunity, some companies package these services and offer them in a developer-friendly way. Heroku is one of these cloud platform providers, and it can help you deploy, manage and scale your web app.

In this tutorial, you’ll learn how to:

  • Create a new app in Heroku and set some basic configuration.
  • Configure the Postgres database add-on.
  • Build a Docker image of your Vapor app, and access the database provided by Heroku.
  • Use Heroku’s Container Registry to upload your Docker image, and deploy the container.
  • Automate the release process by making Heroku build and release your app’s Docker image on each push to your Git repository.
Note: Besides basic Swift knowledge, this tutorial requires a Heroku account, the Heroku CLI and Docker Desktop installed on your machine. Before starting, you might want to get familiar with some Docker concepts by reading this great tutorial by Audrey Tam about the basics of Docker on macOS or my previous tutorial, Developing and Testing Server-Side Swift with Docker and Vapor.

Getting Started

Start by clicking the Download Materials button at the top or bottom of this page. The materials contain the sample Vapor app you’ll use with this tutorial. It’s a familiar friend from the Server-Side Swift book and video course: the TIL app, a web app and API for searching and adding acronyms.

Unzip the file, and with Xcode or your favorite text editor, open the starter folder. You’ll build and run it soon, but for now, it’s worth familiarizing yourself with the code. The files inside the Controllers, Models and Migrations directories are the backbone of this app. Also very important, and the only Swift file you’ll modify in this tutorial, is the configure.swift file. Look at how it configures the app and also the contents of configureLocalDatabase().

Building the Docker Image

Before jumping straight into the deployment and Heroku sections, it’s important to do a quick recap on how to build and run a Docker image, so you can first run your app locally.

Using the Dockerfile

The Dockerfile is the recipe Docker uses to build your app images, which you can later deploy onto containers. If Docker is new to you, refer to Developing and Testing Server-Side Swift with Docker and Vapor, to learn more about it.

The starter sample project already includes a Dockerfile that’s ready for production deployments. This is basically the same file present in Vapor’s official template project.

Building the Image

After opening your preferred terminal application, navigate to the starter project folder. Then, run the command below:

docker build . --tag til-app

A few notes about this command:

  • It tells Docker to build an image. The . character represents the current directory, and it’s where Docker looks for the Dockerfile.
  • By default, Docker looks for a file named Dockerfile within that path. If you use a Dockerfile with a different name — as another file for development or testing — the --file parameter would be required.
  • The --tag parameter helps Docker to identify this image. Docker uses this tag name when it needs to run a container based on this image.

Once you run this command, Docker starts by pulling the base Swift image. It then runs all the commands described in Dockerfile. This includes downloading the Swift package dependencies, building the app with the Swift compiler and then copying the app binary into a slimmer running image, ideal for deployments.

Running the Image Locally

After a few minutes, Docker will finish building your app image. Now, it’s time to run it locally to make sure everything looks good.

The only service the app needs is a PostgreSQL database available. You don’t have to install Postgres on your machine, create the database and configure access. Docker Compose can do all that. The starter project also provides the docker-compose.yml file, which can download the Postgres image and serve it to the app.

Run this command to make Docker Compose prepare the Postgres container:

docker compose run --rm start_dependencies

This ensures that the database container is up, running and ready to receive connections from the app. start_dependencies creates a temporary container, which won’t be needed after the database is up. Therefore, you use --rm to tell Docker to remove it after the command returns.

To start the app container using the image you built in the previous section, run the command below:

docker compose up app

Now, visit http://localhost:8080 in your browser, and you’ll see the TIL home page:

The TIL app running locally with Docker

The TIL app running locally with Docker

Run the following call to get some server information, which ServerInfoController provides:

curl http://localhost:8080/server-info

The response contains three properties:

  • Date the server started running.
  • Platform — macOS or Linux.
  • App environment.

Notice that the app responds with docker-local as the app environment. When later deploying the app to Heroku, you’ll learn how to change that without the need to modify the app code.

Fantastic! You’ve built and run the image on your local machine. In a later section, you’ll perform some changes to allow deployment. But first, a quick section about Heroku will introduce it to you or refresh your memory.

Getting to Know Heroku

Heroku is one of the most popular PAAS — platform as a service — providers. It also helps remove the need to manage hardware or virtual machines, servers and DNS. Heroku allows developers to deploy and scale web apps using containers. These containers deployed at Heroku are called dynos. You can scale your app to run on any specified number of dynos based on its resource demands.

Besides supplying you with the infrastructure to run your app containers, Heroku also provides add-ons. Add-ons are services that are necessary for your web apps. Web apps might need a PostgreSQL or MongoDB database, a CDN or a Redis cache — maybe even all of them, and more. With Heroku, setting up these resources is a breeze!

Note: If you’ve previously worked with Heroku in other programming languages, such as NodeJS or Ruby, you might’ve used a Procfile file for deployments. This tutorial only covers Dockerfile– and heroku.yml-based deployments, but not Procfile-based deployments.