미분류

Docker Container Anti Patterns

This blog will explain 10 containers anti-patterns that I’ve seen over the past few months:

  1. 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. ELK stack could be used to store and process logs. If managed volumes are used during early testing process, then remove them using -v switch with the docker rm command.
  2.  IP addresses of container – 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.
  3. Run a single process in a container – A Dockerfile has use one CMD 그리고 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. Its important to follow separation of concerns pattern when creating Docker images. This will make managing your containers, collecting logs, updating each individual process that much harder. You may consider breaking up application into multiple containers and manage them independently.
  4. 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 its supposed to be running.
  5. Keep your image lean – Create a new directory and include Dockerfile and other relevant files in that directory. Also consider using .dockerignore to remove any logs, source code, logs etc before creating the image. Make sure to remove any downloaded artifacts after they are unzipped.
  6. Create image 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.
  7. Security credentials in 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 또는 ENTRYPOINT to specify a script. This script will pull the credentials from a third party and then configure your application.
  8. latest tag: Starting with an image like 카우치베이스 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 refer to an older version. Taking an application into production requires a fully controller environment with exact version of the image. Read this Docker: The latest confusion post by fellow Docker Captain @adrianmouat.  Make sure to always use tag when running a container. For example, use couchbase:enterprise-4.5.1 instead of just 카우치베이스.
  9. Impedance mismatch – Don’t use different images, or even different tags in 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.
  10. 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.

Adding more based upon discussion on twitter …

  1. Root user – Don’t run containers as root user. The host and the container share the same kernel. If the container is compromised, a root user can do more damage to the underlying hosts. Use RUN groupadd -r couchbase && useradd -r -g couchbase couchbase to create a group and a user in it. Use the USER instruction to switch to that user. Each USER creates a new layer in the image. Avoid switching the user back and forth to reduce the number of layers. Thanks to @Aleksandar_78 for this tip!
  2. Dependency between containers – Often applications rely upon containers to be started in a certain order. For example, a database container must be up before an application can connect to it. The application should be resilient to such changes as the containers may be terminated or started at any time. In this case, have the application container wait for the database connection to succeed before proceeding further. Do not use wait-for scripts in Dockerfile for the containers to startup in a specific order. Particularly waiting for a certain number of seconds for a particular container to start is very fragile. Thanks to @ratnopam for this tip!

What other anti-patterns do you follow? Docker for Java developers is a self-paced hands-on workshop that explains how to get started with Docker for Java developers. Interested in a more deep dive tutorial? Watch this 2-hours tutorial from JavaOne! couchbase.com/containers shows how to run Couchbase in a variety of frameworks.

이 기사 공유하기

작가

아룬 구프트는 Couchbase의 개발자 옹호 부문 부사장입니다. 그는 Sun, Oracle, Red Hat에서 10년 이상 개발자 커뮤니티를 구축하고 이끌었습니다. 그는 복수 기능군을 갖춘 팀을 이끌고 전략, 계획, 실행, 콘텐츠, 마케팅 캠페인 및 프로그램 개발과 실행에 대한 깊은 전문 지식을 보유하고 있습니다. 그 이전에는 Sun의 엔지니어링 팀을 이끌었으며, Java EE 팀의 창립 멤버입니다. 구푸타는 기술 분야에 대한 2,000개 이상의 블로그 게시물을 작성했습니다. 그는 수많은 주제에 대해 40개 이상의 국가에서 폭넓은 강연 경험을 보유하고 있으며, 3년 연속 JavaOne Rock Star상을 수상했습니다. 또한 그는 미국에서 Devoxx4Kids 지부를 설립했으며, 어린이들에게 기술 교육을 지속적으로 추진하고 있습니다. 기술 분야에 대한 다수의 책의 저자이자 열정적인 러너인 그는 전 세계를 누비며 Java Champion로 활동하고 있으며, JUG 리더이자 JUG Dream Team 멤버인 NetBeans Dream Team의 일원입니다. 그는 @arungupta라는 계정을 통해 쉽게 연락하실 수 있습니다.

댓글 남기기

데이터베이스의 확장성을 과거의 일로 남겨두세요

각 스택 추가마다 추가 비용이 발생하고 관리해야 할 항목도 더 많아집니다. 2분 안에 절약할 수 있는 금액을 추산해 보세요.