Using your Docker image on Docker Compose
By using Compose, we have achieved running the default NGINX image and changing the default HTML page that was displayed. Since we have started utilizing Compose, we will proceed with using and testing custom Docker images.
For our use case, we want to develop an NGINX image that prints logs in JSON format since it’s feasible for tools such as CloudWatch (https://aws.amazon.com/cloudwatch/), StackDriver (https://cloud.google.com/products/operations), and ELK Stack (https://www.elastic.co/elastic-stack/) to persist data in JSON format and offer enhanced querying capabilities by having field conditions based on JSON elements.
The problem will require us to identify how NGINX defines the current logging format. Since we have a container already running through Compose, we will shell into the container and check the configuration:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dc0ca7ebe0cb nginx "/docker-entrypoint.…" 7 hours ago Up 7 hours 0.0.0.0:8080->80/tcp chapter1-nginx-1 $ docker exec -it chapter1-nginx-1 cat /etc/nginx/nginx.conf user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
By finding our running container using docker ps
and issuing cat
, through the container shell, we retrieved the current log_format
from the instance by checking the /etc/nginx/nginx.conf
file. We will change this format to JSON and build a custom Docker image preloaded with that format.
We will copy the file locally to apply the change:
$ docker cp chapter1-nginx-1:/etc/nginx/nginx.conf nginx.conf
By editing nginx.conf
instead of log_format
, we set the json
format:
log_format main escape=json '{"remote_addr":"$remote_addr","remote_user":"$remote_user","time":"[$time_local]","request":"$request",' '"status":"$status","body_bytes_sent":"$body_bytes_sent","http_referer":"$http_referer",' '"http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for"}';
Our file will look like this:
user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main escape=json '{"remote_addr":"$remote_addr","remote_user":"$remote_user","time":"[$time_local]","request":"$request",' '"status":"$status","body_bytes_sent":"$body_bytes_sent","http_referer":"$http_referer",' '"http_user_agent":"$http_user_agent","http_x_forwarded_for":"$http_x_forwarded_for"}'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; include /etc/nginx/conf.d/*.conf; }
Now that we have the config file needed, we will create the base NGINX image that will use this configuration. The Dockerfile will be the following:
FROM nginx COPY nginx.conf /etc/nginx/nginx.conf
Let’s build the image:
$ docker build -t custom-nginx:0.1 .
Let’s go ahead and use it with the recently created docker-compose.yaml
file:
services: nginx: image: custom-nginx:0.1 ports: - 8080:80 volumes: - ./static-site:/usr/share/nginx/html $ docker compose up … chapter1-nginx-1 | 2022/02/10 08:09:27 [notice] 1#1: start worker process 33 chapter1-nginx-1 | {"remote_addr":"172.19.0.1","remote_user":"","time":"[10/Feb/2022:08:09:33 +0000]","request":"GET / HTTP/1.1","status":"200","body_bytes_sent":"177","http_referer":"","http_user_agent":"curl/7.77.0","http_x_forwarded_for":""} …
By now, Compose runs successfully on your application that also uses the custom Docker image. So far, Compose was sufficient to use a custom image and also include some modification at runtime such as mounting a file as well as doing port mapping. The results were the same as the ones we would expect if we run the application using Docker commands.