How to create an effective Docker image for a Python project
Docker images are powerful tools for distributing Python projects, but it's important to keep them as clean as possible.
Docker is the industry standard software for packaging and deploying applications in containers. Docker images are the platform on which you can build and run applications.
To fully unlock Docker's potential, you need to optimize images for efficiency, security, and productivity. This ensures your applications run smoothly within the Docker ecosystem.
Here's a detailed guide on how to do just that through a real-life example, showing you how to containerize a desktop application developed with Python .
Start with the most basic image
One of the factors that affects the effectiveness of Docker images is the choice of base image. You should start with a minimal image that includes only the components essential for running the application.
The images you use should also come from a reputable source that provides updates and security patches. It also has an active community and good documentation. This is useful when troubleshooting or looking for help.
For computational applications, choose python:3.11-slim-bookworm , which is a minimal image, reducing image size. In turn, this reduces resource consumption and speeds up image download & deployment.
# Bắt đầu với image cơ bản nhất FROM python:3.11-slim-bookworm AS builder
You can even use a smaller Alpine Linux image, by selecting python:3.11-alpine . However, this image does not include the Python compiler, a package management tool, and popular Python libraries.
Run the application as a non-root user
Running Docker containers as root user can face significant security risks. If a malicious actor gains access to a container running as root, they can exploit vulnerabilities in the container's software to escalate their privileges. They then use those permissions to execute commands with full control over the storage system.
The solution is to run your app as a non-root user. This example desktop application creates and configures user desktops.
# Đặt người dùng không root để đảm bảo an toàn RUN adduser calculator --system # Thêm người dùng vào nhóm máy tính RUN addgroup calculator && adduser calculator calculator
Creating dedicated users for your application limits the permissions available to potential hackers. This makes exploiting the vulnerability more difficult.
Copy necessary files and create virtual environment
Create a virtual environment in a Docker container that isolates dependencies. This prevents conflicts with other packages and applications system-wide. It also ensures version compatibility as you can install the exact version of the dependencies needed by the application without affecting the rest of the system.
Copy necessary files into the container. Then, create a virtual environment for the desktop application using Python's built-in venv module.
# Đặt thư mục hoạt động và sao chép file cần thiết WORKDIR /app COPY app.py . COPY requirements.txt . COPY config.json ./ # Sao chép config.json từ thư mục cục bộ # Tạo môi trường ảo và các phần phụ thuộc RUN python -m venv /venv ENV PATH="/venv/bin:$PATH" RUN /venv/bin/pip install --upgrade pip --no-cache-dir --requirement requirements.txt
Virtual environments are lightweight and efficient because they do not duplicate packages across the system. This helps keep Docker image sizes smaller and reduces resource consumption when containers run.
Minimize layers to increase efficiency
Each instruction in the Dockerfile creates a new layer in the resulting image. Docker uses copy-on-write to manage these layers. Reducing the number of Docker images significantly improves image size and build efficiency. Another way to reduce layers is to merge multiple commands into a single RUN command.
# Giảm thiểu layer để đạt được hiệu quả # Kết hợp lệnh để giảm số lượng layer RUN echo "Build process goes here" && /venv/bin/python -m compileall . && rm -rf __pycache__
Combining the above commands reduces the number of intermediate layers created during image construction.
Secure configuration handling
Handling sensitive information in Docker images can be risky. To improve security, you should use external environment variables and configuration files. In this example, you can create a directory called /config containing the configuration file and set the appropriate ownership.
# Bảo mật xử lý cấu hình RUN mkdir /config && chown calculator:calculator /config
Then copy the config.json file into this folder, making sure it remains separate from the application code.
# Sao chép file config.json file vào container RUN cp config.json /config/config.json ENV CONFIG_PATH=/config/config.json
Separating configuration data from code and applying appropriate permissions will increase the overall security of your Docker image. It ensures only authorized processes or users are allowed access to critical configuration data.
Use multi-phase builds
Multi-stage builds allow you to separate the build environment from the final image. This results in smaller and more focused product images. It also enhances security by excluding build-related tools and files from the final image. Additionally, this reduces potential attacks and security risks associated with unnecessary components.
# Nâng cấp bản build nhiều giai đoạn FROM python:3.11-slim-bookworm COPY --from=builder /etc/passwd /etc/passwd COPY --from=builder /etc/group /etc/group COPY --from=builder /venv /venv COPY --from=builder /config /config COPY --from=builder /app /app # Sao chép code ứng dụng
The above code only copies the necessary elements from the builder phase into the final image. This reduces image size by excluding related tools and files that are not needed for the application.
Enhance security with image scanning tools
You can use scanning tools like Trivy or Clair. They are designed to identify vulnerabilities in the image layer and its dependencies. Use Trivy for calculation applications, to conduct vulnerability scanning.
# Cài đặt Trivy cho Debian/Ubuntu RUN apt-get update && apt-get install -y wget apt-transport-https gnupg lsb-release && wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | apt-key add - && echo "deb https://aquasecurity.github.io/trivy-repo/deb bookworm main" | tee -a /etc/apt/sources.list.d/trivy.list && apt-get update && apt-get install -y trivy
Adding the Trivy vulnerability scanning tool to Docker images is important. That's because it uses the Common Vulnerabilities and Exposures (CVE) database, which is regularly updated with information about known vulnerabilities. This helps you continuously update images with the latest security patches, while also protecting applications from known exploits.
To receive vulnerability reports on images, use the following command:
docker run --rm ` -v /var/run/docker.sock:/var/run/docker.sock ` -v $HOME/Library/Caches:/root/.cache/ ` aquasec/trivy:0.18.3 `
The above command will take some time to run. Once it is completed, you will receive a report as shown below.
The higher the severity, the sooner you should address the vulnerability.
Run the application as a non-root user
To improve safety when running the application as a regular user, run:
# Chạy ứng dụng trong vai trò người dùng không root WORKDIR /app USER calculator # Kích hoạt môi trường ảo và chạy ứng dụng này CMD ["/bin/bash", "-c", "source /venv/bin/activate && python app.py"]
Switching to non-root user mode will greatly reduce the risk of being hacked.
Hope this article is useful to you!
You should read it
- Docker Hub is used by hackers to spread Cryptojacking malware
- Docker best practices you need to know
- 5 useful tips to learn Docker in 2018
- How to use Docker Container
- 10 Best Docker Alternatives 2022
- 5 tips to learn Docker effectively for beginners
- How to Containerize a Nest.js Application Using Docker and Docker Compose
- 6 reasons to use Docker virtualization software
- How to run Docker on Raspberry Pi
- How to safely check desktop applications with Docker
- Containerize Go App with Docker
- Common commands in Docker