Long running services with Docker
Overview
Teaching: 10 min
Exercises: 5 minQuestions
Objectives
Learn how to start containers for a running (web) service
Starting a long-running service in a container
Containers are useful for running services, like web-servers etc. Many come packaged from the developers, so you can start one easily, but first you need to find the one you want to run. You can either search on Docker Hub, or you can use the docker search
command. Nginx is a popular web-server, let’s look for that:
$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 4719 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker c... 877 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable ... 311 [OK]
million12/nginx-php Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS... 76 [OK]
webdevops/php-nginx Nginx with PHP-FPM 63 [OK]
maxexcloo/nginx-php Framework container with nginx and PHP-FPM... 58 [OK]
bitnami/nginx Bitnami nginx Docker Image 20 [OK]
gists/nginx Nginx on Alpine 8 [OK]
evild/alpine-nginx Minimalistic Docker image with Nginx 8 [OK]
million12/nginx Nginx: extensible, nicely tuned for better... 8 [OK]
maxexcloo/nginx Framework container with nginx installed. 7 [OK]
webdevops/nginx Nginx container 7 [OK]
1science/nginx Nginx Docker images based on Alpine Linux 4 [OK]
ixbox/nginx Nginx on Alpine Linux. 3 [OK]
drupaldocker/nginx NGINX for Drupal 3 [OK]
yfix/nginx Yfix own build of the nginx-extras package 2 [OK]
frekele/nginx docker run --rm --name nginx -p 80:80 -p 4... 2 [OK]
servivum/nginx Nginx Docker Image with Useful Tools 2 [OK]
dock0/nginx Arch container running nginx 2 [OK]
blacklabelops/nginx Dockerized Nginx Reverse Proxy Server. 2 [OK]
xataz/nginx Light nginx image 2 [OK]
radial/nginx Spoke container for Nginx, a high performa... 1 [OK]
tozd/nginx Dockerized nginx. 1 [OK]
c4tech/nginx Several nginx images for web applications. 0 [OK]
unblibraries/nginx Baseline non-PHP nginx container 0 [OK]
The official build of Nginx seems to be very popular, let’s go with that:
$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
386a066cd84a: Pull complete
386dc9762af9: Pull complete
d685e39ac8a4: Pull complete
Digest: sha256:3861a20a81e4ba699859fe0724dc6afb2ce82d21cd1ddc27fff6ec76e4c2824e
Status: Downloaded newer image for nginx:latest
Now, in order to run a web server such as a Nginx, we are going to use some additional Docker options, to:
- open up communication ports
- run the container in background
- give the container a specific name
We will also use a number of new Docker commands. Let’s start with a known one:
$ docker run -p 80:80 --name=nginx nginx
The option -p 80:80
tells Docker to map port 80
on the host to port 80
in the container, so you can communicate with it.
We’ve also introduced a second new option: --name
. Docker automatically names containers, but these names don’t reflect the purpose of the container (e.g. pensive_booth
was the name of the nginx container I ran for this example without the --name
option). You can name your container whatever you want, but it’s helpful to give it a name similar to the container you’re using, or the specific service or application you’re running in the container. This can be useful when we need to act on the container while it’s running, e.g. to stop it, or to get logs, as wwe’ll see soon. In this example, we’ve called our container nginx
.
Note also that we didn’t tell docker what program to run, that’s baked into the container in this case. More on that later.
Now, go to your browser and in the address bar enter localhost
if you are running Docker on your machine, or <Your VM's IP Address>
if you are running on a cloud service. You should see a page with a Welcome to nginx! message. On your terminal where you ran the docker command, you’ll see some log information:
172.17.0.1 - - [30/Nov/2016:18:07:59 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0" "-"
2016/11/30 18:07:59 [error] 7#7: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost"
172.17.0.1 - - [30/Nov/2016:18:07:59 +0000] "GET /favicon.ico HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0" "-"
172.17.0.1 - - [30/Nov/2016:18:07:59 +0000] "GET /favicon.ico HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0" "-"
2016/11/30 18:07:59 [error] 7#7: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost"
That’s a good start, but you now have a terminal tied up with nginx, and if you hit CTRL-C
in that terminal, your web-server dies.
To practice a different solution, let’s first stop this container. How to? Use the docker stop
command!
$ docker stop nginx
nginx
Check that it’s gone:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Now let’s go ahead with using the Docker option -d
to run the container in the background instead (daemon mode):
$ docker run -d -p 80:80 --name=nginx nginx
48a2dca14407484ca4e7f564d6e8c226d8fdd8441e5196577b2942383b251106
Go back to your browser, reload localhost
(or <Your VM's IP Address>
), and you should get the page loaded again.
We can view the logs of our nginx service with the docker logs
command, followed by the container name, nginx
:
$ docker logs --follow nginx
172.17.0.1 - - [30/Nov/2016:18:18:40 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0" "-"
This gives us a live look at what is going on in our nginx container (try reloading your webpage and see what the logs look like). Note that the --follow
option keeps the terminal open and will update the logs in real-time. If you omit it, docker logs
would simply display the last few lines of the log file.
If you hit CTRL-C
now, your container is still running, in the background. You can see this with the docker ps
command:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48a2dca14407 nginx "nginx -g 'daemon off" 3 minutes ago Up 3 minutes 443/tcp, 0.0.0.0:80->80/tcp nginx
You can open a shell into the running container, if you wish, using docker exec
. This can be handy for debugging:
$ docker exec -t -i nginx /bin/bash
root@48a2dca14407:/#
root@48a2dca14407:/# exit # or hit CTRL-D
Finally, let’s stop this container:
$ docker stop nginx
nginx
Start a Jupyter web server using a container
How would you use the container image
jupyter/scipy-notebook
to start a Jupyter webserver?A couple of extra requirements:
- assign the name
jupyter
to the container- map the current host working directory as
/home/jovyan/data
(see previous episode)Some hints:
- by default, that image wants to use port
8888
for the container- use the default HTTP port
80
for the host, to navigate to the corresponding page in the web browser using default syntax- no command needs to be specified for that container, the default behaviour is to start the webserver
After you have started it, use
docker logs
to look for an accesstoken
string.Once you are done, stop the container.
Solution
Pull the container:
$ docker pull jupyter/scipy-notebook
Start the webserver:
$ docker run -d -p 80:8888 --name=jupyter -v `pwd`:/home/jovyan/data jupyter/scipy-notebook
Inspect the logs:
$ docker logs jupyter
Use your web browser to go to
localhost
if you are running Docker on your machine, or<Your VM's IP Address>
if you are running on a cloud service.Stop the container:
$ docker stop jupyter
Key Points
You-ve learned how to run long-running services (like a web server) through containers
Use the flag
-d
to run the containers in backgroundUse the flag
-p <host port:<container port>
to map communication portsAdditional options to manage and query containers include
--name
anddocker logs