DEV Community

Cover image for Stop Deploying Manually: Why Your First Dockerfile is a Security Risk

Stop Deploying Manually: Why Your First Dockerfile is a Security Risk

Over at Coding Macaw, we audit a lot of junior engineering portfolios. The most common mistake we see is not a lack of algorithm knowledge. It is a complete misunderstanding of how code actually gets to production.

If you are logging into a remote server via SSH, running a pull command, and restarting a Node or Python process, you are setting yourself up for failure. You need containerization. But even when developers start using Docker, they usually make one massive security mistake.

The Naive Dockerfile

Most developers copy and paste a basic configuration from a tutorial. It usually looks exactly like this:

FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

This works, but it is deeply flawed. By default, processes inside a Docker container run as the root user. If a vulnerability exists in one of your dependencies, an attacker who compromises your application gains root access to the container itself. From there, privilege escalation to the host machine is significantly easier.

Furthermore, this setup destroys your build times. Because the COPY . . command happens before the dependencies are installed, changing a single line of code in your application invalidates the cache, forcing Docker to reinstall every single package from scratch on your next build.

The Production Ready Fix

To fix this, you must explicitly create a restricted user and change the order of your caching layers so your builds take seconds instead of minutes.

Here is the secure approach:

FROM python:3.11-slim

# 1. Create a secure, restricted user
RUN adduser security_user
USER security_user

WORKDIR /app

# 2. Copy ONLY the requirements first to leverage the Docker cache
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 3. Copy the rest of the application code
COPY . .

CMD ["python", "app.py"]
Enter fullscreen mode Exit fullscreen mode

By adding those two RUN and USER commands, you strip away root privileges. By copying requirements.txt first, Docker will cache your heavy dependency installations. Now, when you update your application logic, Docker skips the installation step entirely and just copies the new code.

Launch Your Tech Career This September

Did you find this breakdown helpful? Reading tutorials is great, but executing these concepts in a live environment is how you actually learn.

We noticed a lot of juniors struggling to bridge the gap between local development and production engineering, so we put together a series of completely free, 5 day foundation bootcamps to solve this exact problem.

We are running four distinct tracks this month:

  • September 21st: DevOps (Mastering Docker, CI/CD pipelines, and Linux) and Data Analytics (Python data processing and robust pipeline building).
  • September 28th: Business Analytics (Semantic layers and reporting) and Machine Learning (Applied integrations and RAG pipelines).

These are strictly hands on programs. You will learn, build, and grow your engineering skill set without the massive upfront tuition costs.

Secure your spot today by registering at www.codingmacaw.com or emailing us directly at info@codingmacaw.com if you have any questions about the syllabus.

Are you still deploying manually, or have you made the jump to containerization? Let us know in the comments below!

Top comments (0)