Ahoy, Docker adventurers!🚀 Ready to set sail into the Docker universe? Get ready for simple yet smart container advice – let's make Docker a breeze! 🐳
Best Practices🚩
Let's get straight into it. These are my top 5 best practices to follow when creating a docker container.
✅ Use Smaller Base Image
💡If possible, never ever use big base images.
In Docker Hub when choosing for any images, you will see a bunch of image with it's OS.
If there is an alpine OS
version of the image you are looking for then try to use it always.
It comes with just the tools you need and is very lightweight compared to any other versions🔥.
By doing so you need a very small storage capacity for the image itself and also reduce the attack surface since it does not come with whole bunch of unnecessary tools.
There is a clear performance difference between choosing a lightweight alpine image vs a full blown debian.
Debian: 🐢
time docker run --rm debian sh -c "apt-get update && apt-get install curl"
real 0m27.928s
user 0m0.019s
sys 0m0.077s
Alpine:⚡
time docker run --rm alpine sh -c "apk update && apk add curl"
real 0m5.698s
user 0m0.008s
sys 0m0.037s
✅ Always use .dockerignore
file
💡Use
.dockerignore
to ignore files that are not needed for your container.
Don't push the unnecessary build folders such as dist
or build
and files such as README.md
and Dockerfile
itself. They are not needed to run our container and take up unnecessary space.
So, with .dockerignore
we reduce the image size.😉
✅ Use Specific Docker Image Version
💡When choosing a base image never choose the latest tag.
Use a specific version.
This is a very bad practice ❌
FROM python
You know, in the future, even the smallest change could accidentally bring in a bug, or worse, break your application. 🥲
This is a good practice ✅
FROM python:3.11
✅ Do not use the root
user
💡Try to use the least privileged user when running the container.
By default, when Dockerfile
does not specify a user, it uses the root user. You do not want to run the container with root privilege. ❌
Running the container with root access makes it easier for a hacker to exploit the application inside the container.
To avoid this create a specific user and use it to run all the processes.
# Setup group and user
RUN groupadd -r limiteduser && useradd -g limiteduser limiteduser
RUN chown -R limiteduser:limiteduser /app
# This switches the user from root to limiteduser
USER limiteduser
✅ Use multi-stage builds
💡Again, this helps reduce the image size.
Imagine you're baking a cake: you gather ingredients, mix them, and bake. But what if you could magically remove all the mixing bowls and just keep the final cake?😲
That's what multi-stage builds do! They help build containers in stages, and you only keep the necessary parts.
It allows you to use multiple temporary image during build, but keep only the final image.
This is a sample Dockerfile
example that uses multi-stage build.
# Stage 1: Build the application
FROM python:3.8 AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Stage 2: Create the final container
FROM python:3.8-slim
WORKDIR /app
COPY --from=build /app /app
CMD ["python", "app.py"]
So, that is it for this article. Hope this is useful for every one of you. 🤗
If you think of any other helpful tips that I haven't covered in this article, please don't hesitate to share them in the comments section below. 🔥
Let's stay connected👋
- GitHub: https://github.com/shricodev
- LinkedIn: https://linkedin.com/in/shrijal007
See you next time✌️
Top comments (5)
Alpine may be small, but in my experience it’s also very good at suddenly breaking builds and being the root cause of unexpected issues.
Most of this comes down the implementation of its C library. There are also minor performance considerations when using musl over glibc.
I understand. Alpine's small size might occasionally cause surprises. But I haven't had any issues with it up until now.😮💨
Nice hints!
🙌