Most of the dynamic web applications depend on databases like mysql
,
postgres
, mongodb
etc. However, setting up an environment (or a server) to
work with those services can be a pain. And if you add periodic upgrades,
version management and OS-specific package manager issues, it could really be
a nightmare!
One solution to this problem is Containerization
. This might not be the best
solution for high-volume production apps, but for most of the apps (and at
least for dev environment), it can be a life saver.
In this post, we will be using docker
as our
Containerization Engine to set up a Postgres Service.
For instructions on installing docker, check out this page
Pull Postgres Image
In order to run postgres
inside a Docker container, you will need to use an
image. There are two ways to get that image:
- Pull a trusted, maintained and official
postgres
image from DockerHub. - Pull a base OS image (say CentOS) and run a series of commands on it to work
with
postgres
.
In order pull an image from DockerHub,
Here, I will be pulling the official postgres
image from DockerHub:
Linux Users must use sudo
with docker
$ docker pull postgres:9.3.23
This will take a couple minutes to pull postgres image with tag, 9.3.23
from
DockerHub.
It’s important to use tags here, because docker pulls the latest image if a tag isn’t specified. You don’t want to use an updated postgres without knowledge.
Running the Postgres Container
Now that we have the postgres
image, we can create and run a container using
that image. For a container which is expected to be “long running”, we typically
use docker run
with -d
(detached) option. This allows us to create a
stopped container which can be ran in the background using docker start
.
Moreover, we want to be able to access the container’s port from host
machine which is why we also provide -p
option, which allows us to do port
forwarding from a docker container to the host. Since postgres
runs on
the port 5432
, we want to expose that port from the container and forward it
to host’s 5432
port.
We’re also providing a name
to the container which will allow us to perform
operations on that container without having to know it’s hashed id.
Optionally, we can also provide an environment variable to the container
POSTGRES_PASSWORD
which sets the password to the user postgres
.
So, to launch the postgres
container, use the following command:
$ docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=******* -d postgres:9.3.23
We can now start this container by typing:
$ docker start postgres
To test if postgres container is running as expected we can launch psql
:
$ docker exec -it postgres psql -Upostgres -W
Password for user postgres: ********
psql (9.3.23)
Type "help" for help.
postgres=#
Now, we have a working containerized postgres
service.
Data Persistence
When running a postgres
container, we most likely want to persist the data.
In order to do so across multiple container instances, we can use
Volumes
.
First, let’s stop and remove the current container:
$ docker stop postgres && docker rm postgres
Now, we can create a container which uses a location on the host machine to use
as a volume which will be mounted in the postgres
container to a location where
it stores data (by default: /var/lib/postgresql/data
). This can be done
by using the -v
option:
$ docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=******* -d -v /tmp/postgresdata:/var/lib/postgresql/data postgres:9.3.23
This command will create a directory named postgresdata
in /tmp
folder.
Now, we have a container which persists data to a host volume, that can be used to create another container.
Start postgres
on System Reboot
Docker provides a neat way of restarting a container with different policies. Check out this page for more details.
I like keeping my postgres
container running unless I have explicitly
stopped it. So, I use restart unless-stopped
policy.
So, our final command should look something like this:
$ docker run --name postgres --restart unless-stopped -p 5432:5432 -e POSTGRES_PASSWORD=******* -d -v /tmp/postgresdata:/var/lib/postgresql/data postgres:9.3.23
Conclusion
This kind of a set up can be used for mysql
, phpadmin
and many other services.
I use docker
for all my tools that use tcp
. It makes managing these
tools a lot easier as all I have to maintain is docker
, and everything else
is handled by the maintainers of the image that I’m using. It also works on
multiple operating systems (as long as they support docker
).
Don’t forget to alias the final run
command :)