DevOps
DevOps tutorials for people who want an app to run the same way on every machine, not only on the one it was written on. Learn what each command does before you trust it. A copied command runs just as happily when it is wrong.
Reproduce the error with a non-root container, read the owner numbers and fix it by changing the folder's owner or the container's user. After this, you can tell which side to change and stop reaching for chmod 777.
Run PostgreSQL 18 on a named volume and on a bind mount and compare what each leaves on your disk. After this, you can pick the right mount for a database and mount the right folder.
Run a different program from the same image with --entrypoint, in docker run and in Compose. After this, you can start a shell or a one-time job without rebuilding the image.
Pass variables from your shell, from an env file and from a Compose secret, and make Compose refuse to start when a required one is missing. After this, you can keep real values out of your files and your commands.
Tag, push and pull an image in the order you type the commands, shown against a local registry, with the Docker Hub version written out. After this, you can move an image to another computer.
Keep one base compose.yaml and merge a development override and a production file on top of it. After this, you can see what each environment gets with docker compose config before you run it.
Keep node_modules out of the build context with a .dockerignore file and let npm ci install the packages inside the image. After this, you can cut the context size and avoid copying Windows-built packages into a Linux image.
Tag one build with a version, latest and a commit name, then release the next version without moving the old tag. After this, you can roll back with one command.
Add a pg_isready health check to a database and make the app wait for it with service_healthy. After this, you can stop an app from failing on a database that is still starting.
Add a BuildKit cache mount to pip install so a changed requirements file downloads only the new packages. After this, a dependency change no longer means downloading everything again.
Build a Go service in a multi-stage Dockerfile and ship it in an image well under 50 MB, with a non-root user and a health check. After this, you know why Go gets that small and Node does not.
Add a user to an image, give it only the folder it writes to, and fix the two permission errors you will most likely hit. After this, your containers stop running as root.