Docker for developers: images, containers, networks, and volumes
Docker

Docker for developers: images, containers, networks, and volumes

Nam Nguyen
3 min read
0 views
#docker
#container
#compose
#devops

What Docker solves#

Docker packages an application with its runtime, system dependencies, and startup command into an image that can run consistently across environments. It is especially useful when a project has multiple services or when onboarding needs to be fast and repeatable.

A container is not a small virtual machine. Containers share the host kernel, start quickly, and run from immutable images. Understanding images, containers, networks, and volumes makes Docker far easier to debug.

Image vs container#

An image is a layered blueprint. A container is a running instance of that image. You can delete a container without deleting its image, run many containers from one image, and lose filesystem changes unless data is stored in a volume.

Dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start"]

.dockerignore matters#

Without .dockerignore, build context may include node_modules, local caches, logs, Git history, or secrets. That makes builds slower and increases the risk of leaking data into an image.

Text
node_modules
.next
.git
.env
.env.local
npm-debug.log
coverage
dist

Compose for local stacks#

Docker Compose describes local services, ports, volumes, and environment variables in one file. In the default Compose network, services can call each other by service name.

YAML
services:
  app:
    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:

Networking and volumes#

Port mapping such as 3000:3000 exposes a container port to the host. Between containers, use service names such as db:5432. Inside a container, localhost means that same container, not another service.

Volumes keep data outside the disposable container lifecycle. Use named volumes for local databases and bind mounts for development source code. In production, use managed databases, object storage, or volume systems with backups.

Debug commands#

Terminal
docker ps
docker logs app
docker exec -it app sh
docker inspect app
docker compose config
docker compose logs -f app
docker system df

Production checklist#

  • Use explicit base image versions.
  • Keep secrets out of images.
  • Use .dockerignore to reduce build context.
  • Tag images by commit SHA or release version.
  • Run a clear foreground process as the main command.
  • Expose the correct port and configure health checks.
  • Run as non-root where the base image and framework allow it.
  • Scan images and dependencies regularly.

Primary references#

Share this article

Help others discover this article

Comments

Loading comments...

Loading comments...

Leave a Comment

Your email will not be published

Minimum 10 characters

0 / 5000