like: Note that ports which are not bound to the host (i.e., -p 5432:5432 instead of -p 127.0.0.1:5432:5432) will be accessible from the outside. This also applies if you configured UFW to block this specific port, as Docker manages its own iptables rules. https://docs.docker.com/network/packet-filtering-firewalls/
- using trivy scanner: "trivy image --ignore-unfixed ... "
I'd also fix the very first example. Stuff like LABEL, ENV, EXPOSE, CMD or ENTRYPOINT that rarely ever changes should be at the top, followed by ARG, prior to the first ADD/COPY/RUN statements. That way, you can re-use layer caching more efficiently.
In general, I think it's also a good general idea to keep yourself to one, maximum two RUN statements per image - I've seen it way too many times that some junior writes RUN apt update, RUN apt install -yf foo, RUN apt clean... which will leave all the intermediate crap from apt still part of the final image as the third command (the apt clean) will just set tombstone files [1][2] in the layer's overlay image.
(Side note, it boggles my mind why you can't tell Docker to flatten multiple subsequent "metadata only" layers like LABEL/ENV/CMD/ENTRYPOINT/ARG into one single one)
Additionally, I'd add a warning for multi-stage builds that ARG needs to be redeclared in following stages (a simple ARG xyz is sufficient, no need to repeat a default value), and that CMD/ENTRYPOINT set in the first stage for some reason tend to be overwritten in a stage that is FROM first-stage.
Sometimes, following a security vulnerability, users end up in intense discussions with the maintainers of Docker images.
It's challenging to navigate such situations effectively. The apparent simplicity of Docker images can be deceptive and pose risks. It's important to exercise caution to avoid potential problems.
See:
"Docker Hub image for version 12.4 contains a cryptominer [Confirmed!]"
I'm wondering why it's not more common to indent the stages in a multi-stage build. For me, it's a no-brainer to see at a glance
1. how many stages there are
2. how long they are
3. the dependencies
Taking the example from the article:
FROM node:18-alpine as builder
WORKDIR /app
COPY ./package* .
RUN npm ci
COPY . .
RUN npm run build:client
FROM nginxinc/nginx-unprivileged:1.24 as serve
COPY --from=builder /app/dist /var/www
COPY --from=builder /app/.nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
IMHO it's just so more legible. Without this, it feels like writing C without indentation. Unfortunately the Jetbrains IDEs fail to properly apply syntax highlighting.
I've never really had the chance to try it, but buildah seems like a decent enough choice to build images using basic shell tooling. At least then you don't need to muck around with build-args or other limitations of the dockerfile DSL.
I think Docker has a fairly well designed CLI and I don't find myself having to Google commands for it often. It follows a few pretty consistent patterns that I wish git had tried to stick with rather than the concoction of words and flags for common actions it ended up with.
This looks useful, I wish I'd found it a month ago.
One suggestion: could we have a more printer-friendly version (ie, without large patches of colour and without large patches of black)?
Nice work. I did a little “cheat sheet” a while back which has some Kubernetes and even Windows containers stuff too. Always interesting what parts of systems different developers use based on their requirements. https://github.com/nycdotnet/docker-cheat-sheet
If you're familiar with OOP/language with classes, a fitting analogy could be that a container is an instance of a image, just like you can create instances of classes. The image is the "template" so to say, and the container is the executing of that "template".
So a stopped container could have stuff in it that doesn't exist in the image, as the container has gone through the states of "created > running > stopped" and during the running, you can mutate stuff in the container.
On the other hand, an image never actually runs, only containers created from that image.
I guess you could compare it to VMs as well, where you can have templates/other instances, and clone new instances from that template/other instance. Kind of the same too.
- Security warnings:
like: Note that ports which are not bound to the host (i.e., -p 5432:5432 instead of -p 127.0.0.1:5432:5432) will be accessible from the outside. This also applies if you configured UFW to block this specific port, as Docker manages its own iptables rules. https://docs.docker.com/network/packet-filtering-firewalls/
- using trivy scanner: "trivy image --ignore-unfixed ... "
---------------------
Why the security is important?
- https://sysdig.com/blog/zoom-into-kinsing-kdevtmpfsi/ : "Some of those Docker engines weren’t configured with authentication, which make them a perfect target for Kinsing attacks."
- https://sysdig.com/blog/cloud-defense-in-depth/ ( JULY 4, 2023: Cloud Defense in Depth: Lessons from the Kinsing Malware )
- https://thenewstack.io/kinsing-malware-targets-kubernetes/ ( Jan 13th, 2023 , Kinsing Malware Targets Kubernetes )
- https://stackoverflow.com/search?q=kinsing