Skip to main content

Dockerfile va Image Building

Dockerfile nima?

Dockerfile - bu Docker image yaratish uchun ko'rsatmalar to'plami bo'lgan matn fayli. U image yaratish jarayonini avtomatlashtiradi va takrorlanishini ta'minlaydi.

Dockerfile'ning afzalliklari:

  • Automation: Manual qadamlarni avtomatlashtirish
  • Reproducibility: Bir xil image'larni qayta yaratish
  • Version Control: Git bilan versiyalash
  • Documentation: Image yaratish jarayonini hujjatlash
  • Sharing: Jamoa bilan ulashish

Asosiy Tamoyillar:

  1. Har bir ko'rsatma yangi layer yaratadi
  2. Layer'lar cache'lanadi (tezlashtirish uchun)
  3. Ko'rsatmalar yuqoridan pastga qarab bajariladi
  4. Har bir RUN ko'rsatmasi yangi container yaratadi

Dockerfile Sintaksisi

Asosiy Format

# Comment (izoh)
INSTRUCTION arguments

# Misol:
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y python3

Naming Convention

  • Fayl nomi: Dockerfile (katta harf bilan)
  • Extension yo'q
  • Directory'da asosan bitta Dockerfile

Asosiy Ko'rsatmalar (Instructions)

1. FROM - Base Image

Sintaksis:

FROM <image>[:<tag>] [AS <name>]

Misollar:

# Official Ubuntu image
FROM ubuntu:20.04

# Alpine Linux (minimal)
FROM alpine:latest

# Node.js runtime
FROM node:16-alpine

# Multi-stage build uchun nom berish
FROM node:16 AS builder

# Scratch (absolutely empty)
FROM scratch

Best Practices:

  • Specific tag ishlatish (latest emas)
  • Minimal base image tanlash (Alpine)
  • Official image'larni afzal ko'rish

2. RUN - Buyruq Bajarish

Sintaksis:

# Shell form
RUN <command>

# Exec form
RUN ["executable", "param1", "param2"]

Misollar:

# Package'lar o'rnatish
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
curl \
&& rm -rf /var/lib/apt/lists/*

# Python dependencies
RUN pip install flask requests

# Multiple commands (shell form)
RUN mkdir -p /app/data && \
chown -R appuser:appuser /app

# Exec form
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", "nginx"]

Best Practices:

# BAD: Ko'p layer yaratadi
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# GOOD: Bitta layer
RUN apt-get update && apt-get install -y \
python3 \
curl \
&& rm -rf /var/lib/apt/lists/*

3. COPY va ADD - Fayllarni Nusxalash

COPY (tavsiya etiladi):

COPY <src> <dest>
COPY ["<src>", "<dest>"] # path'larda space bo'lsa

ADD (qo'shimcha xususiyatlar bilan):

ADD <src> <dest>

Misollar:

# Bitta fayl nusxalash
COPY app.py /app/

# Multiple fayllar
COPY *.py /app/

# Directory nusxalash
COPY ./src /app/src

# Ownership bilan
COPY --chown=user:group files /app/

# ADD: URL'dan yuklash
ADD https://example.com/file.tar.gz /tmp/

# ADD: Tar faylni avtomatik extract qilish
ADD archive.tar.gz /app/

COPY vs ADD:

COPYADD
Faqat local fayllarURL'dan yuklash
Oddiy nusxalashTar avtomatik extract
XavfsizroqKo'proq xususiyat
Tavsiya etiladiFaqat kerak bo'lganda

4. WORKDIR - Working Directory

WORKDIR /path/to/workdir

Misollar:

# Working directory o'rnatish
WORKDIR /app

# Nisbiy path
WORKDIR /app
WORKDIR src # /app/src ga o'zgaradi

# Nested directories
WORKDIR /var/log/myapp

# Environment variable ishlatish
ENV APP_HOME /application
WORKDIR $APP_HOME

Best Practices:

# BAD
RUN cd /app && python app.py

# GOOD
WORKDIR /app
RUN python app.py

5. ENV - Environment Variables

ENV <key>=<value>
ENV <key1>=<value1> <key2>=<value2>

Misollar:

# Bitta variable
ENV NODE_ENV=production

# Multiple variables
ENV NODE_ENV=production \
PORT=3000 \
DEBUG=false

# Path o'zgaruvchisi
ENV PATH="/app/bin:$PATH"

# Database configuration
ENV POSTGRES_HOST=localhost \
POSTGRES_PORT=5432 \
POSTGRES_DB=myapp

6. EXPOSE - Port'larni E'lon Qilish

EXPOSE <port> [<port>/<protocol>]

Misollar:

# HTTP port
EXPOSE 80

# HTTPS port
EXPOSE 443

# Multiple ports
EXPOSE 80 443

# TCP va UDP
EXPOSE 80/tcp
EXPOSE 53/udp

# Dynamic port
ENV PORT=8080
EXPOSE $PORT

Muhim: EXPOSE faqat documentation uchun, actual port publishing uchun docker run -p ishlatiladi.

7. CMD - Default Command

# Exec form (tavsiya etiladi)
CMD ["executable", "param1", "param2"]

# Shell form
CMD command param1 param2

Misollar:

# Web server ishga tushirish
CMD ["nginx", "-g", "daemon off;"]

# Python script
CMD ["python", "app.py"]

# Shell script
CMD ["./start.sh"]

# Shell form
CMD npm start

# Parameters bilan
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:application"]

8. ENTRYPOINT - Entry Point

ENTRYPOINT ["executable", "param1", "param2"]

CMD vs ENTRYPOINT:

# Faqat CMD
CMD ["echo", "hello"]
# docker run myapp -> "hello"
# docker run myapp echo "world" -> "world"

# Faqat ENTRYPOINT
ENTRYPOINT ["echo"]
# docker run myapp -> ""
# docker run myapp "hello" -> "hello"

# ENTRYPOINT + CMD
ENTRYPOINT ["echo"]
CMD ["hello"]
# docker run myapp -> "hello"
# docker run myapp "world" -> "world"

Amaliy Misol:

# Flexible script
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["app"]

# docker run myapp -> ./docker-entrypoint.sh app
# docker run myapp backup -> ./docker-entrypoint.sh backup

9. USER - Foydalanuvchi

USER <user>[:<group>]
USER <UID>[:<GID>]

Misollar:

# User yaratish va ishlatish
RUN adduser --disabled-password --gecos '' appuser
USER appuser

# UID bilan
USER 1000:1000

# Root'dan qaytish
USER root
RUN apt-get update
USER appuser

# Group bilan
RUN groupadd -r mygroup && useradd -r -g mygroup myuser
USER myuser:mygroup

10. VOLUME - Volume Mount Points

VOLUME ["/data"]
VOLUME /var/log /var/db

Misollar:

# Bitta volume
VOLUME ["/app/data"]

# Multiple volumes
VOLUME ["/app/data", "/app/logs"]

# Directory yaratish bilan
RUN mkdir -p /app/uploads
VOLUME ["/app/uploads"]

11. ARG - Build Arguments

ARG <name>[=<default value>]

Misollar:

# Default value bilan
ARG NODE_VERSION=16

# Build time'da ishlatish
FROM node:${NODE_VERSION}-alpine

# Multiple args
ARG BUILD_DATE
ARG VERSION=1.0.0
ARG AUTHOR="Developer"

# Label'larda ishlatish
LABEL build-date=$BUILD_DATE
LABEL version=$VERSION

Build vaqtida:

docker build --build-arg NODE_VERSION=18 --build-arg VERSION=2.0.0 .

12. LABEL - Metadata

LABEL <key>=<value> <key>=<value> ...

Misollar:

# Version information
LABEL version="1.0.0"
LABEL description="My web application"

# Maintainer info
LABEL maintainer="developer@example.com"

# Multiple labels
LABEL version="1.0.0" \
description="My web application" \
vendor="MyCompany" \
release-date="2024-01-01"

# Build arguments ishlatish
ARG BUILD_DATE
ARG VERSION
LABEL build-date=$BUILD_DATE
LABEL version=$VERSION

Docker Build Jarayoni

1. Basic Build

# Current directory'da Dockerfile
docker build .

# Tag bilan
docker build -t myapp:latest .

# Specific Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .

# Build context
docker build -t myapp:latest /path/to/context

2. Build Options

# Build arguments
docker build --build-arg NODE_VERSION=18 -t myapp .

# No cache
docker build --no-cache -t myapp .

# Target stage (multi-stage)
docker build --target production -t myapp:prod .

# Platform specific
docker build --platform linux/amd64 -t myapp .

# Progress output
docker build --progress=plain -t myapp .

3. .dockerignore

.dockerignore fayli build context'ga kirmasligi kerak bo'lgan fayllarni belgilaydi:

# Version control
.git
.gitignore

# Dependencies
node_modules
*.log

# OS files
.DS_Store
Thumbs.db

# IDE
.vscode
.idea

# Build files
dist
build
*.tar.gz

# Environment files
.env.local
.env.production

# Documentation
README.md
docs/

Multi-Stage Builds

Multi-stage build - bu bitta Dockerfile'da bir nechta FROM ko'rsatmalarini ishlatish orqali image size'ni kamaytirish usuli.

1. Basic Multi-Stage

# Build stage
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Production stage
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

2. Complex Multi-Stage

# Development dependencies
FROM node:16 AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci

# Build stage
FROM dependencies AS builder
COPY . .
RUN npm run build
RUN npm run test

# Production dependencies
FROM node:16-alpine AS prod-deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

# Final production image
FROM node:16-alpine AS production
WORKDIR /app
COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]

3. Build Specific Stage

# Faqat builder stage'ni build qilish
docker build --target builder -t myapp:builder .

# Production stage
docker build --target production -t myapp:prod .

Real-World Misollar

1. Node.js Application

# Node.js web application
FROM node:16-alpine AS base

# Install dumb-init for proper signal handling
RUN apk add --no-cache dumb-init

# Create app user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
FROM base AS deps
RUN npm ci --only=production && npm cache clean --force

# Build stage
FROM base AS builder
COPY . .
RUN npm ci
RUN npm run build

# Production stage
FROM base AS runner
ENV NODE_ENV=production

# Copy files from previous stages
COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist
COPY --from=builder --chown=nextjs:nodejs /app/public ./public

# Switch to non-root user
USER nextjs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1

# Start application
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]

2. Python Flask Application

# Python Flask application
FROM python:3.9-slim AS base

# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PIP_NO_CACHE_DIR=1
ENV PIP_DISABLE_PIP_VERSION_CHECK=1

# Create app user
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# Set working directory
WORKDIR /app

# Install Python dependencies
FROM base AS deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Development stage
FROM deps AS development
COPY requirements-dev.txt .
RUN pip install --no-cache-dir -r requirements-dev.txt
COPY . .
CMD ["flask", "run", "--host=0.0.0.0", "--debug"]

# Production stage
FROM deps AS production
COPY . .

# Change ownership
RUN chown -R appuser:appgroup /app

# Switch to non-root user
USER appuser

# Expose port
EXPOSE 5000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5000/health || exit 1

# Start application
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:app"]

3. React Frontend Application

# React application
FROM node:16-alpine AS base
WORKDIR /app

# Install dependencies
FROM base AS deps
COPY package*.json ./
RUN npm ci

# Build stage
FROM deps AS builder
COPY . .
RUN npm run build

# Production stage with nginx
FROM nginx:alpine AS production

# Copy nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf

# Copy built application
COPY --from=builder /app/build /usr/share/nginx/html

# Add health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost || exit 1

# Expose port
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]

4. Go Application

# Go application
FROM golang:1.19-alpine AS builder

# Install git and ca-certificates
RUN apk add --no-cache git ca-certificates

# Set working directory
WORKDIR /app

# Copy go mod files
COPY go.mod go.sum ./

# Download dependencies
RUN go mod download

# Copy source code
COPY . .

# Build application
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Final stage
FROM scratch

# Copy ca-certificates for HTTPS requests
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Copy binary
COPY --from=builder /app/main /main

# Expose port
EXPOSE 8080

# Start application
ENTRYPOINT ["/main"]

Best Practices

1. Image Size Optimization

# Use multi-stage builds
FROM node:16 AS builder
# ... build process
FROM node:16-alpine AS final
COPY --from=builder /app/dist ./dist

# Use .dockerignore
# Add node_modules, .git, etc.

# Minimize layers
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*

# Use specific tags
FROM node:16.14.2-alpine3.15

2. Security Best Practices

# Don't run as root
RUN adduser --disabled-password --gecos '' appuser
USER appuser

# Use official images
FROM node:16-alpine

# Keep images updated
FROM ubuntu:20.04
RUN apt-get update && apt-get upgrade -y

# Don't add secrets
# Use docker secrets or environment variables

# Use COPY instead of ADD
COPY package.json ./

# Set proper permissions
COPY --chown=appuser:appuser . ./

3. Performance Best Practices

# Order layers by change frequency
FROM node:16-alpine
WORKDIR /app

# 1. Dependencies (changes rarely)
COPY package*.json ./
RUN npm ci

# 2. Source code (changes often)
COPY . .

# Use build cache efficiently
# Put frequently changing commands last

# Use specific COPY commands
COPY package.json ./
COPY src/ ./src/
# Instead of: COPY . .

4. Maintenance Best Practices

# Use labels for metadata
LABEL maintainer="developer@example.com"
LABEL version="1.0.0"
LABEL description="My application"

# Document exposed ports
EXPOSE 3000

# Add health checks
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1

# Use environment variables for configuration
ENV NODE_ENV=production
ENV PORT=3000

# Document volumes
VOLUME ["/app/data"]

Debugging Dockerfile

1. Build Issues

# Verbose build output
docker build --progress=plain --no-cache .

# Build specific stage
docker build --target builder .

# Interactive debugging
docker run -it intermediate_image_id bash

2. Layer Inspection

# Image history
docker history myapp:latest

# Layer details
docker inspect myapp:latest

3. Common Issues

# Issue: COPY fails
# Solution: Check .dockerignore and paths

# Issue: Permission denied
# Solution: Check USER and file permissions

# Issue: Command not found
# Solution: Check PATH and installation

# Issue: Large image size
# Solution: Use multi-stage builds and alpine images

Docker image building - bu DevOps engineering'ning eng muhim qismlaridan biri. Dockerfile'ni to'g'ri yozish orqali kichik, xavfsiz va samarali image'lar yaratish mumkin!