Deploying NGINX and NGINX Plus with Docker

Introduction

The Docker open platform includes the Docker Engine – the open source runtime that builds, runs, and orchestrates containers – and

Docker containers enable developers to focus their efforts on application “content” by separating applications from the constraints of infrastructure. Dockerized applications are instantly portable to any infrastructure – laptop, bare-metal server, VM, or cloud – making them modular components that can be readily assembled and re-assembled into fully featured distributed applications and continuously innovated on in real time.

For more information about Docker, see What is Docker? or the full Docker documentation.

Using the NGINX Docker Image

You can create an NGINX instance in a Docker container using the NGINX image from Docker Hub.

Let’s start with a very simple example. To launch an instance of NGINX running in a container and using the default NGINX configuration, run this command:

# docker run --name mynginx1 -P -d nginx \
fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d

This command creates a container named mynginx1 based on the NGINX image. The command returns the long form of the container ID, which is used in the name of log files; see Managing Logging.

The -d option specifies that it run in detached mode, which means that the container continues to run until stopped but does not respond to commands run on the command line. We discuss later how to interact with the container.

The -P option tells Docker to map the ports exposed in the container by the NGINX image – ports 80 and 443 – to ports on the Docker host that are randomly selected from the range between 49153 and 65535. We do this because otherwise there will be conflicts on ports 80 and 443 if we later create multiple NGINX containers on the same Docker host. The port mappings are dynamic and are set each time the container is started or restarted. If you want static port mappings, use the -p option to set them manually.

To verify that the container was created and is running, and to see the port mappings, we run docker ps. (We’ve split the output across multiple lines here to make it easier to read.)

# docker ps
CONTAINER ID  IMAGE         COMMAND               CREATED         STATUS         
fcd1fb01b145  nginx:latest  "nginx -g 'daemon of  16 seconds ago  Up 15 seconds  

PORTS                                         NAMES
0.0.0.0:49166->443/tcp, 0.0.0.0:49167->80/tcp mynginx1

The PORTS field in the output reports that port 49167 on the Docker host is mapped to port 80 in the container. Another way to verify that NGINX is running is to make an HTTP request to that port. The code for the default NGINX welcome page appears:

# curl http://localhost:49167
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
 body {
 width: 35em;
 margin: 0 auto;
 font-family: Tahoma, Verdana, Arial, sans-serif;
 }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="https://www.nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Working With the NGINX Docker Container

So now we have a working NGINX Docker container, but how do we manage the content and the NGINX configuration? And what about logging?

A Note About SSH

It is common to enable SSH access to NGINX instances, but the NGINX image does not have OpenSSH installed, because Docker containers are generally intended to be for a single purpose (in this case running NGINX), and for normal operations there is no need to have shell access directly to the NGINX container. Instead we’ll use other methods supported by Docker. For a detailed discussion of alternatives to SSH access, see Why You Don’t Need to Run SSHd in Your Docker Containers.

Managing Content and Configuration Files

There are several ways you can manage the content served by NGINX and the NGINX configuration files. Here we cover a few of the options.

Managing Logging

You can configure either default or customized logging.

Controlling NGINX

Since we do not have direct access to the command line of the NGINX container, we cannot use thenginx command to control NGINX. Fortunately we can use signals to control NGINX, and Docker provides the kill command for sending signals to a container.

To reload the NGINX configuration, run this command:

# docker kill -s HUP container-name

To restart NGINX, run this command to restart the container:

# docker restart container-name

Deploying NGINX Plus with Docker

So far we have discussed Docker for the open source NGINX product, but you can also use it with the commercial version, NGINX Plus. The difference is you first need to create an NGINX Plus image, because as a commercial offering NGINX Plus is not available at Docker Hub. Fortunately, this is quite easy to do.

Creating a Docker Image of NGINX Plus

To generate an NGINX Plus image, first create a Dockerfile. Here we provide examples for Ubuntu 14.04 and CentOS 7.0 that you can use as templates for other operating systems. For both Ubuntu and CentOS, you have to download your version of the nginx-repo-crt and nginx-repo-key files fromhttp://cs.nginx.com, the portal for NGINX Plus customers who have purchased or are evaluating NGINX Plus. Copy the files to the directory where the Dockerfile is located (the Docker build context).

As with open source NGINX, by default the NGINX Plus access and error logs are linked to the Docker log collector. No volumes are specified, but you can add them if desired, or these Dockerfiles can be used to create base images from which you can create new images with volumes specified, as described previously.

By default, no files are copied from the Docker host as a container is created. You can add COPYdefinitions to the Dockerfiles, or the image you create can be used as the basis for another image as described above.

Dockerfile for Ubuntu

FROM ubuntu:14.04

MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"

# Set the debconf front end to Noninteractive
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections

RUN apt-get update && apt-get install -y -q wget apt-transport-https

# Download certificate and key from the customer portal (https://cs.nginx.com)
# and copy to the build context
ADD nginx-repo.crt /etc/ssl/nginx/
ADD nginx-repo.key /etc/ssl/nginx/

# Get other files required for installation
RUN wget -q -O /etc/ssl/nginx/CA.crt https://cs.nginx.com/static/files/CA.crt
RUN wget -q -O - http://nginx.org/keys/nginx_signing.key | apt-key add -
RUN wget -q -O /etc/apt/apt.conf.d/90nginx https://cs.nginx.com/static/files/90nginx

RUN printf "deb https://plus-pkgs.nginx.com/ubuntu `lsb_release -cs` nginx-plus\n" >/etc/apt/sources.list.d/nginx-plus.list

# Install NGINX Plus
RUN apt-get update && apt-get install -y nginx-plus

# forward request logs to Docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

Dockerfile for CentOS

FROM centos:centos7

MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"

RUN yum install -y wget

# Download certificate and key from the customer portal (https://cs.nginx.com)
# and copy to the build context
ADD nginx-repo.crt /etc/ssl/nginx/
ADD nginx-repo.key /etc/ssl/nginx/

# Get other files required for installation
RUN wget -q -O /etc/ssl/nginx/CA.crt https://cs.nginx.com/static/files/CA.crt
RUN wget -q -O /etc/yum.repos.d/nginx-plus-7.repo https://cs.nginx.com/static/files/nginx-plus-7.repo

# Install NGINX Plus
RUN yum install -y nginx-plus

# forward request logs to Docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

Creating the NGINX Plus Image

With the Dockerfilenginx-repo-crt, and nginx-repo.key files in the same directory, run the following command there to create a Docker image called nginxplus (as before, note the final period):

# docker build --no-cache -t nginxplus .

Note the --no-cache option, which tells Docker to build the image from scratch and ensures the installation of the latest version of NGINX Plus. If the Dockerfile was previously used to build an image and you do not include the --no-cache option, the new image uses the version of NGINX Plus from the Docker cache. (We purposely do not specify a version in the <Dockerfile so that the file does not need to change at every new release of NGINX Plus.) Omit the --no-cache option if it’s acceptable to use the NGINX Plus version from the previously built image.

Output like the following from the docker images ngxinplus command indicates that the image was created successfully:

# # docker images nginxplus
REPOSITORY  TAG     IMAGE ID      CREATED        VIRTUAL SIZE
nginxplus   latest  ef2bf65931cf  6 seconds ago  281.3 MB

To create a container named mynginxplus based on this container, run this command:

# docker run --name mynginxplus -P -d nginxplus

You can control and manage NGINX Plus containers in the same way as NGINX containers.

Summary

NGINX, NGINX Plus, and Docker work extremely well together. Whether you use the open source NGINX image from the Docker Hub repository or create your own NGINX Plus image, you can easily spin up new instances of NGINX and NGINX Plus in Docker containers. You can also easily create new Docker images from the base images, making your containers even easier to control and manage. One thing to keep in mind is that NGINX Plus is sold on a per-instance basis, so each Docker container running NGINX Plus requires a separate subscription.

There is much more to Docker than we have been able to cover in this article. More information is available at www.docker.com.

By Rick Nelson for the NGINX Blog.

 

 

 

 

Top