Every now and then, I end up setting up a new tech stack, or a library for a project, just to try out something new.

I have been using Docker for a while now, and I have found it to be a great way to run anything as a container without polluting the host machine with unnecessary packages and dependencies.

Here is my workflow for running anything as a container.

1. Create a Dockerfile

Find a base image that closely matches with your needes, add customizations on top of it as needed. I usually pick between these docker images:

  • Python: python:3.13 is a good choice for new python projects.
  • Node: node:23 is a good choice for new Node.js projects.
  • Ruby: ruby:3.4 is a good choice for new Ruby projects.
  • Ubuntu: ubuntu:24.10 is a good choice if you are building something from scratch, but you don’t care about image size.
  • Alpine: alpine:3.21 is a good choice if you want a minimal image, and build a custom image from there for production use cases.

Note that more images are available on Docker Hub, and you could search for official images that closely matches with your needes.

Two more things to consider:

  • All the above images could be downloaded with latest tag, but I don’t prefer that approch because I like to lock image versions, which ensure that dependecies don’t break.
  • I also try to not use unofficial images on dockerhub because they tend not to be actively maintained, and also could have security vulnerabilities, malicious or not.

So, once you pick your image, you can use that as your base image, and add further customizations.

Here is a sample template to get started:

FROM python:3.13

RUN pip install --upgrade pip

ENV HELLO=WORLD

ENTRYPOINT ["echo", "Hello, World!"]

2. Build the image

docker build -t hello-world:latest .

3. Run the image

docker run -it hello-world:latest

Run the image with a bash shell

docker run -it hello-world:latest /bin/bash

Run the image with current directory mounted

docker run -it -v $(pwd):/app hello-world:latest /bin/bash

Run the image with port forwarding

docker run -it -p 8080:8080 hello-world:latest /bin/bash

Now, there many different options when you run a docker image, and we will use this to run anything with docker.

Note that you don’t want to keep running docker build after every file change, so you could volume mount with -v option so that you app code is mounted into the container when you run it.

But, you will still want to rebuild docker image if any dependencies change. Which is acceptable.

So, if you are working on a python flask project, you can run the following command to start the flask server, and do a volume mount so that your changes are reflected immediately.

docker run -it -v $(pwd):/app -p 8080:8080 flask-app:latest

Note that I am assuming that you have already built and setup flask app as a Docker image, and have setup necessary entrypoint.

However, for a use case like running a flask app, I would probably go with poetry to manage dependencies on the host machine, and avoid the overhead of running it as a docker container.

But, use-cases where I have to install a lot of dependencies, and native libraries, or more complex setups, I would definitely choose docker over running it on the host machine.

4. Prune system for a clean slate

Docker images and their layers take a lot of disk space. So every once in a while depending on how frequently I use docker, I usually run a full clean up to free up disk space. This also sometimes addresses unexplinable errors during docker builds.

docker system prune -a

5. Push the image to a registry

Sometimes you might want to push your image to a container registry so that other people can use it.

For public images, you can use Docker Hub because it is indexed on search engines, and for private images, there are several options, you can use GitHub Container Registry, or AWS ECR, or Google Container Registry.

How to push to Docker Hub:

export DOCKER_USERNAME=my-username
docker login
docker tag my-image:latest ${DOCKER_USERNAME}/my-image:latest
docker push ${DOCKER_USERNAME}/my-image:latest

How to push to GitHub Container Registry:

Goto https://github.com/settings/tokens/new?scopes=write:packages to create a new Private Access Token with write:packages only scope.

export CR_PAT=<YOUR_PRIVATE_ACCESS_TOKEN>
export GITHUB_USERNAME=<YOUR_GITHUB_USERNAME>
echo $CR_PAT | docker login ghcr.io -u ${GITHUB_USERNAME} --password-stdin
docker tag my-image:latest ghcr.io/${GITHUB_USERNAME}/my-image:latest
docker push ghcr.io/${GITHUB_USERNAME}/my-image:latest

How to push to AWS ECR:

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin XXXXXX.dkr.ecr.us-east-1.amazonaws.com
docker tag my-image:latest XXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-image:latest
docker push XXXXXX.dkr.ecr.us-east-1.amazonaws.com/my-image:latest

How to push to Google Container Registry:

gcloud auth configure-docker
docker tag my-image:latest gcr.io/my-project/my-image:latest
docker push gcr.io/my-project/my-image:latest