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:
- Har bir ko'rsatma yangi layer yaratadi
- Layer'lar cache'lanadi (tezlashtirish uchun)
- Ko'rsatmalar yuqoridan pastga qarab bajariladi
- 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 (
latestemas) - 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 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:
| COPY | ADD |
|---|---|
| Faqat local fayllar | URL'dan yuklash |
| Oddiy nusxalash | Tar avtomatik extract |
| Xavfsizroq | Ko'proq xususiyat |
| Tavsiya etiladi | Faqat 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 /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 /app/node_modules ./node_modules
COPY /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 /app/node_modules ./node_modules
COPY /app/dist ./dist
COPY /app/public ./public
# Switch to non-root user
USER nextjs
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK \
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 \
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 /app/build /usr/share/nginx/html
# Add health check
HEALTHCHECK \
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 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Copy binary
COPY /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 /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 . ./
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 \
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!