Docker Application Containerization Services

Docker application containerization: writing Dockerfiles, Docker Compose, Registry setup, image optimization, multi-stage builds, and container security.
Showing 30 of 37All 1054 services
Configure Hadolint for Dockerfile Linting
Simple
from 4 hours to 2 days

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1359
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1112

How does application containerization solve the reproducibility problem?

A Python application runs on a developer's laptop. In staging, it crashes with ModuleNotFoundError. In production, it crashes with PermissionError on a directory that doesn't exist. Three environments — three sets of problems. Containerization with Docker solves exactly this: not abstract "isolation", but the specific problem of runtime environment reproducibility.

We have been working with Docker for over 7 years and have containerized more than 50 services — from Go microservices to PHP monoliths and heavy ML pipelines in Python. In every project, we encountered typical mistakes: images of 2 GB, build times of 15 minutes on a clean cache, secrets baked into layers, applications running as root. Here's how to fix it.

Why are multi-stage builds the industry standard?

A single-stage Dockerfile for a Go application carries the entire toolchain: compiler, packages, sources. The resulting image is 1.1 GB with 150+ vulnerabilities. A multi-stage build leaves only the binary and CA certificates:

FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server . FROM scratch COPY --from=builder /app/server /server COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ EXPOSE 8080 ENTRYPOINT ["/server"] 

Image size is 8–15 MB instead of 1.1 GB — a reduction of up to 100 times. Attack surface is minimal: no shell, no package manager. Trivy finds 0 vulnerabilities in such an image (if the binary is compiled without CVE dependencies). For Node.js, we apply a similar pattern: separate stages for dependencies, build, and final with a non-root user.

How does BuildKit speed up builds by 6x?

BuildKit (active by default in modern Docker versions) adds parallel execution of independent stages and mount caches that are not included in the final image. Example for Go:

FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod \ go mod download COPY . . RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 go build -o server . 

First build takes 4 minutes. Subsequent builds only compile changed packages in 40 seconds. In CI, you can export cache via type=registry — it works on any runner. Docker documentation describes all the options.

What is the correct order of instructions for layer caching?

Docker invalidates the layer cache and all subsequent layers when any file used in the instruction changes. A typical mistake is copying all code before installing dependencies. The correct order: first copy manifests (package.json, go.mod), run installation, then copy source code. This way, code changes do not re-trigger npm ci or go mod download. This speeds up the build in CI by 30–50% for a typical project.

How to manage private registries?

Registry When to use
ECR (AWS) AWS infrastructure, native integration with EKS
GCR / Artifact Registry GCP infrastructure
ACR (Azure) Azure
Harbor On-premise, self-hosted with Trivy and RBAC
GitHub Container Registry Projects on GitHub Actions

Harbor is the only self-hosted option with a full set: Trivy scanning, replication between registries, immutable tags. The latest tag in production is an anti-pattern: Kubernetes will not pull the image if it already exists on the node. The correct approach is to tag by git SHA or semver: app:1.4.2.

What does vulnerability scanning in CI provide?

Trivy scans OS packages, language dependencies, and Dockerfile configuration. Minimal integration in GitLab CI reduces critical vulnerabilities by 90% in a month:

trivy-scan: image: aquasec/trivy:latest stage: security script: - trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed --format json --output trivy-report.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA 

--ignore-unfixed — do not fail on vulnerabilities without fixes. --severity HIGH,CRITICAL — avoid pipeline noise. In .trivyignore, document accepted risks with justification.

Container security: what else to check

Besides CVEs, always check:

  • Root user. Always add a USER instruction. The application must not run as root.
  • Read-only filesystem. docker run --read-only or securityContext.readOnlyRootFilesystem: true in Kubernetes. Writable directories via tmpfs.
  • Secrets. BuildKit with --secret passes secrets into the build without writing them to the layer. Example: RUN --mount=type=secret,id=npm_token NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci.
  • Distroless images (Google Distroless) — minimal images without shell. Fewer CVEs, smaller attack surface.

Wikipedia confirms these practices as industry standard.

Docker Compose for local development

depends_on with condition: service_healthy — wait for the actual readiness of the service:

services: app: depends_on: db: condition: service_healthy db: image: postgres:15-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 

docker-compose.override.yml — for dev-specific settings (volume mounts, debug ports) that are not included in production.

How we work on containerization

  1. Audit current Dockerfiles and CI pipelines. Identify bottlenecks: image size, caching, security.
  2. Design multi-stage build architecture for your stack.
  3. Develop and optimize Dockerfiles (caching, non-root, distroless).
  4. Set up private registry, scanning in CI/CD, and immutability policies.
  5. Documentation and team training: runbook for developers, 1-2 workshops.

Average cloud resource savings after implementation: 35%. If you recognize your problems in the described cases — contact us for an audit of your infrastructure. Get an assessment in 1 day.

Company experience

Over 7 years working with Docker and Kubernetes. 50+ containerization projects — from startups to enterprise. Certified Kubernetes (CKA, CKAD). Experience with Yandex Cloud, AWS, GCP, Selectel. Each project ends with handover of documentation and an operations plan.

Time estimates

Task Timeline
Containerizing a single service from scratch 1–2 days
Optimizing existing Dockerfiles + CI cache 1–2 days
Setting up Harbor with Trivy and replication 2–4 days
Setting up scanning in CI for N services 2–3 days
Audit and recommendations (no fixes) 1 day

Cost is calculated individually after project assessment. Request a consultation — we will analyze your infrastructure and suggest the optimal solution. Reduce build time and cloud resource costs now.