Techie April 2022
Definition
Dockerizing an application, packages it in a docker image that can be run in a container and easily scaled by generating more instances. These containers can also be run in different machines without requiring extra configurations since environment configurations are encapsulated and reporduced.
During the process, we specify everything needed to run the application and the instructions for creating the docker image in a special file called Dockerfile (with no extension).
Since we can only have one application or service per container, the database has to be encapsulated in a separate container. Another file called docker-compose (a yaml file) is used to provide the instructions for spinning up a docker container with the database inter-linked with the app.
NB: Every docker container has it’s own networking interface i.e like Operating Systems running in different networks with different IP addresses. If you open the terminal and run the ifconfig command, you will see the docker containers’ network interfaces in addition to your local machine’s network interface.
This document assumes that you already have Docker installed on your operating system.
Create the Dockerfile
At the root of the rails project, create a file called Dockerfile, with no extension. Let’s add the following in a stepwise fashion:
1 . Add an operating system containing the project’s version of ruby using the “from” directive.
Alpine Linux is a lightweight operating system and therefore a great fit for docker containers or any system that is network-based and dedicated for a single purpose only, like in the case of routers.
2 . Add database dependencies and other project dependencies.
This example uses a postgres database. Project dependencies may vary depending on the rails project.
Remove the package manager cache: The “ && rm -rf /var/cache/apk/* “ removes all the installation files that were downloaded for the project dependencies, to free up space for the docker image.
3 . Create a directory called “app” to put our project in the root of the docker image.
4 . Copy the contents of the current directory (rails project) to the app directory created in step 3 above. The period stands for the current directory path.
5 . Set gems location.
We want to save our project’s gems in a directory called gems at the root of the docker image. This overrides the default location.
6 . Install yarn and then bundle.
7 . Define the entry point.
This defines the command to be run when the docker image is started.
8 . Bind the server to 0.0.0.0
9 . Expose the port for the project.
Normally, rails apps run on port 3000
10 . Final Dockerfile.
11 . Build the Dockerfile.
cd to the root of your project and run this command.
e.g
If you have an account on docker, you can you can specify your account name like so:
You can also specify the version number like so:
12 . Run the docker app
NB: You may need to prepend “sudo” for it work if you have not specified a user in your Dockerfile, but remember that it is bad practice to use privileged permissions as it can allow an attacker to escalate privileges on the host. Always specify a user with least privileges in the Dockerfile.
The first (local’s) port is beeing mapped to the second (container’s )port. Open the browser and navigate to the localhost on port 3005.
You’ll get an error because the containerized app has a different networking interface and cannot connect to the database on the local machine. To fix that, we have to spin up other containers that will contain the database servers. Before that, shutdown the server and follow the next step.
Create Database Servers with docker-compose
1 . Create a docker-compose File
Create a docker-compose.yml file at the root of the project and add the following:
2 . Define docker-compose file version
It’s important to provide the supported version.
3 . Define the services
Services can include postgres server, redis server, rails app created in Dockerfile (then referenced using volumes key) etc
NB: Notice how we used volumes key to persist the postgres data so that we dont lose it when the app restarts.
The final docker-compose.yml file should resemble this:
4 . Finally, run docker-compose
Run this command at the root of the project. This will boot up the app. Open the browser and navigate to localhost on port 3005.
NB: You may need to prepend “sudo” for it work if you have not specified a user in your Dockerfile, but remember that it is bad practice to use privileged permissions as it can allow an attacker to escalate privileges on the host. Always specify a user with least privileges in the Dockerfile.
You now have the database containers and the app container up and running and mapped together.
Thanks for reading, see you in the next one!