Docker Container Anti-Patterns

DZone 's Guide to

Docker Container Anti-Patterns

Arun Gupta provides a listing of his top ten anti-patterns regarding Docker containers.

· Cloud Zone ·
Free Resource

This article will focus on 10 container anti-patterns that I’ve seen over the past few months.

Data or Logs in Containers

Containers are ideal for stateless applications and are meant to be ephemeral. This means no data or logs should be stored in the container — otherwise, they’ll be lost when the container terminates. Instead, use volume mapping to persist them outside the containers. The ELK stack could be used to store and process logs. If managed volumes are used during early in the testing process, then remove them using a -v switch with the docker rm command.

IP Addresses of Containers

Each container is assigned an IP address. Multiple containers communicate with each other to create an application, for example, an application deployed on an application server will need to talk with a database. Existing containers are terminated and new containers are started all the time. Relying upon the IP address of the container will require constantly updating the application configuration. This will make the application fragile. Instead, create services. This will provide a logical name that can be referred independent of the growing and shrinking number of containers. And it also provides a basic load balancing as well.

Run a Single Process in a Container

A Dockerfile uses one CMD and ENTRYPOINT. Often, CMD will use a script that will perform some configuration of the image and then start the container. Don’t try to start multiple processes using that script. It's important to follow separation of concerns pattern when creating Docker images. This will make managing your containers, collecting logs, and updating each individual process that much harder. You may consider breaking up applications into multiple containers and managing them independently.

Don’t Use docker exec

The docker exec command starts a new command in a running container. This is useful for attaching a shell using the docker exec -it {cid} bash. But other than that, the container is already running the process that it's supposed to be running.

Keep Your Image Lean

Create a new directory and include the Dockerfile and other relevant files in that directory. Also consider using .dockerignore to remove any logs, source code, et.c before creating the image. Make sure to remove any downloaded artifacts after they are unzipped.

Create Images From a Running Container

A new image can be created using the docker commit command. This is useful when any changes in the container have been made. But images created using this are non-reproducible. Instead, make changes in the Dockerfile, terminate existing containers, and start a new container with the updated image.

Security Credentials in a Docker Image

Do not store security credentials in the Dockerfile. They are in clear text and checked into a repository. This makes them completely vulnerable. Use -e to specify passwords as runtime environment variable. Alternatively --env-file can be used to read environment variables from a file. Another approach is to used CMD or ENTRYPOINT to specify a script. This script will pull the credentials from a third party and then configure your application.

The latest Tag

Starting with an image like couchbase is tempting. If no tags are specified, then a container is started using the image couchbase:latest.  This image may not actually be latest and instead could refer to an older version. Taking an application into production requires a fully controlled environment with the exact version of the image. Read this Docker: The latest confusion post by fellow Docker Captain @adrianmouat. Make sure to always use the right tag when running a container. For example, use couchbase:enterprise-4.5.1 instead of just couchbase.

Impedance Mismatch

Don’t use different images, or even different tags in the dev, test, staging, and production environment. The image that is the “source of truth” should be created once and pushed to a repo. That image should be used for different environments going forward. In some cases, you may consider running your unit tests on the WAR file as part of maven build and then create the image. But any system integration testing should be done on the image that will be pushed in production.

Publishing Ports 

Don’t use -P to publish all the exposed ports. This will allow you to run multiple containers and publish their exposed ports. But this also means that all the ports will be published. Instead use -p to publish specific ports.

What other anti-patterns do you follow?

anti-patterns ,cloud ,containers ,docker

Published at DZone with permission of Arun Gupta , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}