If you have ever written Dockerfiles to containerize your applications, which include steps like FROM COPYand a few other commands. After saving the file, you run docker build . and you may get an error. It will take a few minutes to pull base image and you may get an error response, missing package, or an incorrect path. This can be time consuming to catch error on runtime by following steps in loop from writing, build, fail, fix and repeat. This can reduce developer productivity and not worth it.Docker DX extension can help to reduce this debug time and catch the error when you are writing the Dockerfile instead of waiting and watching terminal or CI pipeline to build container image. I recently find it saving my time and in this article I will explain it, part of my development setup. First, I will install Docker DX extension on vscode marketplaceDocker DXOnce it’s installed, you get: Auto-completion of Dockerfiles and linting Live build linting powered by Buildx and Buildkit - same checks a real build runs, just surfaced when you typeVulnerability flags on the base images you referenceCompose intelligence that actually understands how your docker-compose.yml relates to the Dockerfile it’s building fromBake file support if you’re using docker buildx bakeA step-through debugger from Dockerfile builds, I will share more about it later in the articleWriting a simple DockerfileHere’s an example Dockerfile for a node app that has a few human errors baked in. FROM node:14 WORKDIR /app COPY package.json . RUN npm install COPY . . EXPOSE 3000 CMD npm start In order for the extension to be used, you need to have a Docker engine running in your environment. This extension has cross platform support so it works on Windows, MacOS and Linux in both arm and amd64.By reading it over, nothing screams “wrong” but this is one of the Dockerfile, I’d have written a few years ago without thinking twice. But with the extension installed, the editor doesn’t let it slide quietly. Open the Problems panel (Ctrl + Shift + M on MAC) and a few issues will show up: DockerFile errorsThe base image is the big one - node:16 gets flagged by vulnerability scanning. This will remind you to use the latest node version. So, you don’t need to wait for a vulnerability scanning report to come and this can not only reduce security team effort but help to ship code with less vulnerabilities, not just optimize developer productivity.Next warning about, CMD npm start written in shell form instead of exec. It technically works initially, app will run but there is a catch, npm ends up running as a Process ID 1 inside the container, sitting on top of your actual Node process instead of being replaced by it. That matters because when Docker wants to stop a container, it sends a signal called SIGTERM to whatever’s running as PID1. In this case, npm will get the signal not your app. NPM is not reliable to propagate that signal down to its child process it started. So, node app either never receive it or receive it too late and Docker kills the container outright once its grace period runs out. You won’t notice any of this in local dev, where you are usually hitting Ctrl+C anyway. You will notice this in the production, the first time you deploy a new version and in-flight requests get dropped instead of finishing cleanly, because the app never gets the chance to shut down itself gracefully. In some cases, AI generated code will even add such configuration without finding the bug and it can turn into a 2am production incident 2 weeks after deployment. So, fixing before deployment is the right approach than finding this in postmortem. So, improved version of Dockerfile:FROM node:20-alpine WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --omit=dev COPY . . EXPOSE 3000 CMD ["node", "server.js"] node:20-alpine gets you a supported, much smaller image. npm ci respects the lockfile exactly instead of npm's more forgiving resolution — which is what you actually want in a build. Exec-form CMD means signals get forwarded the way they should. Watch the Problems panel as you make each change, it clears out in real time, and that loop is really the whole pitch of this extension.Now wire it up with ComposeA lone Dockerfile is only half the story for most real apps. Let's add a docker-compose.yml that runs this alongside Postgres.services: web: build: . ports: - "3000:3000" environment: DATABASE_URL: postgres://app:app@db:5432/app depends_on: - db db: image: postgres:16-alpine environment: POSTGRES_USER: app POSTGRES_PASSWORD: app POSTGRES_DB: app volumes: - db-data:/var/lib/postgresql/data volumes: db-data: This is where it stops feeling like a YAML linter and starts feeling like something that actually understands your project. Because the extension reads both the Compose schema and the Dockerfile sitting right next to it, a few things just work: hover over build: . and you get a preview pulled from the actual Dockerfile it resolves to, which matters a lot once you've got more than one service. Reference an env var, network, or volume that isn't defined anywhere (including in a file you included) and you get a warning immediately, instead of finding out when docker compose up throws a cryptic connection error. Autocomplete inside blocks like environment: or ports: is schema-aware too, not just guessing at indentation.Try breaking it on purpose, rename the db service to database, but leave DATABASE_URL and depends_on still pointing at db. You should see that mismatch flagged before you ever get to watch the app fail to connect at runtime.When linting isn't enoughSometimes you need more than a warning, you need to know what's really happening inside a build step while it's happening. This is the part of the extension almost nobody talks about, and it might be the most useful piece: a real step-through debugger for Dockerfile builds, sitting on top of Buildx. RUN npm ci --omit=dev is failing in a way the log output doesn't explain. Instead of littering the file with RUN echo "here" and rebuilding over and over, click in the gutter next to that RUN line, same as setting a breakpoint in a JS or Python file and start a debug session.VS Code pauses the build right at that instruction and drops you into a shell inside the container, at that exact layer. Poke around the filesystem, check what actually got copied in, run the failing command by hand, and see immediately why it's blowing up — no rebuilding from scratch every time you want to test a theory.This needs the standalone Buildx binary with Debug Adapter Protocol support, not just whatever ships bundled with Docker Desktop, at least as of writing. If the debug option doesn't show up for you, that's usually the reason, worth checking your Buildx version.So what actually changedNothing about the mistakes themselves changed, an old base image, a shell-form CMD, a typo'd service name in Compose are all things any of us write without thinking. What changed is when you find out. Instead of a failed build, a confusing runtime crash, or a security scan flagging it three sprints later, you get told while your cursor is still sitting on the line that caused it.It's a small shift, but it adds up over a week of real work, fewer round trips through docker build, fewer "why won't this container start" sessions, and fewer surprises when a base image gets called out in a security review after it's already shipped.If you want to go further, the extension's repo has a DEBUGGING.md that goes deeper on the build debugger, and an FAQ.md that covers tuning or turning off the vulnerability warnings if they get too noisy for your workflow.
How Docker DX Catches Dockerfile Errors Before You Build
Full Article
Original Source
Read the full article at Hackernoon →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.