Docker Basics : Connecting Containers
- Launch named containers.
- Create links between containers.
- Use names and links to communicate across containers.
- Use these features to decouple app dependencies and reduce complexity.
We will learn how to use name and links to expose one container's ports to another. Why? So each component of your app such as DB, web app can run independently with its own dependencies. We're going to:
- get two images: a PostgreSQL database image and a Ruby on Rails application image.
- start containers from each image.
- link the containers running our Rails application and database using Docker's link primitive.
Let's pull down the database image.
$docker pull training/postgres
Pulling repository training/postgres 258105bea10d: Download complete 511136ea3c5a: Download complete ... Status: Image is up to date for training/postgres:latest
Let's review the image:
$docker images training/postgres
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE training/postgres latest 258105bea10d 12 months ago 364.6 MB
Let's look at the Dockerfile that built this image.
FROM ubuntu:14.04 MAINTAINER Docker Education Team <firstname.lastname@example.org> ENV PG_VERSION 9.3 RUN locale-gen en_US.UTF-8 RUN apt-get update RUN apt-get -y install postgresql postgresql-client postgresql-contrib RUN pg_dropcluster $PG_VERSION main && pg_createcluster --locale en_US.UTF-8 $PG_VERSION main RUN echo "host all all 0.0.0.0/0 trust" >> /etc/postgresql/$PG_VERSION/main/pg_hba.conf RUN echo "listen_addresses='*'" >> /etc/postgresql/$PG_VERSION/main/postgresql.conf RUN service postgresql start && \ su postgres sh -c "createuser -d -r -s docker" && \ su postgres sh -c "createdb -O docker docker" && \ su postgres sh -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE docker to docker;\"" EXPOSE 5432 CMD ["su", "postgres", "-c", "/usr/lib/postgresql/$PG_VERSION/bin/postgres -D /var/lib/postgresql/$PG_VERSION/main/ -c config_file=/etc/postgresql/$PG_VERSION/main/postgresql.conf"]
This image is based on ubuntu:14.04 base image. It specifies a number of environment variables. It install the required packages and configures the PostgreSQL database settings. It exposes port 5432. It runs the PostgreSQL database when a container is launched from the image.
will expose a port to our Rails application in another container, not to the host.
Let's luanch a container from the training/postgres image.
$docker run -d --name database training/postgres
Let's check the container is running.
$docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 802443b6a4f2 training/postgres:latest "su postgres -c '/us 30 seconds ago Up 28 seconds 5432/tcp database
Our container is launched and running a PostgreSQL database. Using the --name flag, we have given it a name: database. Container names are unique. We are going to use that name.
Let's pull down our Rails application image.
$docker pull training/notes
Pulling repository training/notes d347176e7bb1: Download complete 511136ea3c5a: Download complete ... Status: Downloaded newer image for training/notes:latest
$docker images training/notes
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE training/notes latest d347176e7bb1 9 months ago 476.7 MB
Let's look at the Dockerfile that built this image.
FROM ubuntu:14.04 MAINTAINER Docker Education Team <email@example.com> RUN apt-get update RUN apt-get install -y ruby ruby-dev libpq-dev build-essential RUN gem install sinatra bundler --no-ri --no-rdoc ADD . /opt/dockernotes WORKDIR /opt/dockernotes RUN bundle install EXPOSE 3000 CMD bundle exec rails s
This image is based on the ubuntu base image using the 14.04 tag to get Ruby 1.9.3. It installs the required packages. Adds the Rails application itself to the /opt/dockernotes directory. Exposes port 3000. Runs Ruby on Rails when a container is launched from the image.
Let's launch a container from the training/notes image. Let's setup the application database schema.
docker run --name rails training/notes rake db:create db:migrate
The container fails to start.
could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
The Rails application needs access to the database to run.
Container names are unique. You can only have one container named rails at a time. Let's delete our container so we can use that name again.
$docker rm rails
Let's link our container to our existing PostgreSQL container. The rake command below is a one-time process that needs to be done in all Rails applications to initialize the database.
$docker run -i -t --name rails --link database:db training/notes rake db:create db:migrate
== CreateNotes: migrating ==================================================== -- create_table(:notes) -> 0.0062s == CreateNotes: migrated (0.0064s) ===========================================
The --link flag connects one container to another. We specify the name of the container to link to, database, and an alias for the link 'db'.
We can remove the container.
docker rm rails
The link provides a secure tunnel between containers. On our database container port 5432 has been exposed to the linked container. Docker will automatically set environment variables in our container, to indicate connection information. Let's see that information.
docker run --rm --link database:db training/notes env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=1d5cae52b3f6 DB_PORT=tcp://172.17.0.33:5432 DB_PORT_5432_TCP=tcp://172.17.0.33:5432 DB_PORT_5432_TCP_ADDR=172.17.0.33 DB_PORT_5432_TCP_PORT=5432 DB_PORT_5432_TCP_PROTO=tcp DB_NAME=/reverent_ptolemy/db DB_ENV_PG_VERSION=9.3 HOME=/
Each variable is prefixed with the link alias: db. It includes connection information plus any environment variables set in the database container via ENV instructions. The --rm removes the container after it exits, as this is not a long running container.
Now we've configured our database. Let's start the application in a new container.
$docker run -d -p 80:3000 --name rails --link database:db training/notes
You will see:
Check the container is running.
$docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c8f36026e8a2 training/notes:latest "/bin/sh -c 'bundle 29 seconds ago Up 28 seconds 0.0.0.0:80->3000/tcp rails
Browse to http://192.168.59.103:80 to view the Rails application. You can find the IP address to use by running:
$boot2docker ip 192.168.59.103
$ docker kill rails database rails database
$ docker rm rails database rails database
We can use container names to stop and remove them. We removed them so we can re-use their name later.
In this article, we learned how to launch named containers, create links between containers, use name and links to communicate across containers. Use these features to decouple app dependencies and reduce complexity.
Ace the Technical Interview
- Easily find the gaps in your knowledge
- Get customized lessons based on where you are
- Take consistent action everyday
- Builtin accountability to keep you on track
- You will solve bigger problems over time
- Get the job of your dreams
Take the 30 Day Coding Skills Challenge
Gain confidence to attend the interview