Dockerizing a Flask Application
By: John Miner
Tags: Docker Compose, DevOps, Flask, Docker, Python

Have you ever been building a project and testing it locally then find out you can’t get it to run in production for the life of you? I know I have and I expect most developers experience this at some point as well. The problem might not be too obvious or maybe it is obvious but the platform that you are trying to deploy to such as Heroku doesn’t support what you are trying to do. It can be quite frustrating to know you can get a project working locally but not be able to show it to the world. So what can you do?

The answer isn’t too obvious, at least for me it wasn’t. That particular project called playground went undeveloped for about a year before I was able to deploy it properly and I’m about to tell you how I did it.

You’ll need some things for this project:

First, you’ll need an application I’m using a simple flask one, but you could probably follow along with any language or framework that you are familiar with.

You’ll need Docker installed on your system

You’ll want a Domain name. Don’t have one? You can register one at name.com

You’ll need a server that can run docker. Don’t have one? You can rent one on digital ocean, I suggest that you use the one with Caprover installed. Which you can find here. Having Caprover on your server makes deploying with docker a breeze.

Setting things up for your application.

You’ll need to add a Dockerfile at the root of your project.

$ cd ~/your/project/root/directory

$ touch Dockerfile

You’ll need to define how you’re application is set up in the Dockerfile. You can find more information on Dockerfile documentation here.

# Inside the Dockerfile # Our first step is to install a base image.

# I'm using python so I'll be using a python image.

# Please use an image optimised for your language or find a defualt # image like ubuntu or alpine linux # STEP 1: Install base image.

FROM python:3.7-slim-buster # STEP 2: Copy the source code in the current directory to the

# container. Store it in a folder named /app.

ADD . /app # STEP 3: Install any requirements that you might have.

RUN python3 -m pip install -r /app/requirements.txt # STEP 4: Set working directory to /app so we can execute commands

# in it

WORKDIR /app # STEP 5: Declare any needed environment variables

ENV FLASK_APP=app.py

ENV FLASK_ENV=development # STEP 6: Expose the port that your app is running on.

EXPOSE ${PORT} # STEP 7: Give the command to run your application.

CMD ["python3", "app.py"]

If you have made a docker file you are now ready to try and run your application in a local dockerization. We’ll have to build our docker container. Make sure you use -t to tag it with a readable name or else it’ll end up as a hash. Then use docker run to run your application, use -d to daemonize it if you want, and use -p exposedport:port to connect the port you exposed in step 6 to your machine. Make sure your application is set up to run on 0.0.0.0 or else you won't be able to see it from outside of the docker container.

$ cd ~/your/project/root/directory

$ docker build -t yourapps/tagname .

$ docker run -p portnumber:portnumber yourapps/tagname

After running the above commands your application should be reachable at http://localhost:portnumber.

Optional next step (suggested if using Caprover)

For Caprover to work properly you’ll need a captain-definition file.

$ cd ~/your/project/root/directory

$ touch captain-definition

Inside the file, you can specify some info but we’ll just point it to our Docker file. More info about the captain definition file can be found here. Inside the file you’ll just need:

{

"schemaVersion": 2,

"dockerfilePath": "./Dockerfile"

}

Optional next step (to easily run your dockerized app)

There is another file we can add to manage the application, it can control how it's built and connect the exposed ports. The file is called docker-compose.yml it makes it extremely easy to run your app for someone who’s not familiar with your project and it can be used to add docker volumes (permanent storage for docker apps) though I didn’t need them.

$ cd ~/your/project/root/directory

$ touch docker-compose.yml

Inside the file, you’ll need to define where you are building your app, what command it needs, and you can specify the ports you want to connect. More info can be found here. Here’s what mine looks like:

version: '3.7'

services:

web:

build: .

command: python3 app.py

ports:

- "5000:5000"

Pretty short and simple. Now to run your app all you need to do is just

$ docker-compose up

and your app will start up like magic without having to pass in the ports or anything. Easy-peasy!

Alright, I’ve dockerized my app. Now what?

If you have gotten your app to run in a local docker container you have gotten past the hard part. The next step is to update our domain name’s a-record to point to our server’s IP address. If you used digital ocean you can find your IP address right where I covered mine up ;) Ps. Don’t ever expose your server IP, it’ll make it easier to get hacked.

Okay, I found the IP address now how do I update the a-record?

It depends on where you registered the domain name but if you used name.com you click more info about your domain name, scroll to the section domain details and click on manage DNS records under the DNS heading. When adding the a-record you should see something like this.