Цель: понять весь основной workflow Docker:
Application
↓
Dockerfile
↓
docker build
↓
Docker Image
↓
docker run
↓
Container
↓
Ports
↓
Volumes
↓
Networks
↓
Registry
↓
Kubernetes
PART 1 — Проверяем Docker
docker --version
Проверяем, работает ли Docker:
docker info
Главная команда помощи:
docker --help
Объяснение:
Docker Engine — запускает контейнеры
Docker CLI — команды docker, которые мы вводим
Docker Image — шаблон
Docker Container — запущенный экземпляр image
PART 2 — Первый контейнер
Запустите:
docker run hello-world
Что произошло:
docker run hello-world
↓
Docker ищет image локально
↓
Image нет
↓
Docker скачивает его из registry
↓
Создает container
↓
Запускает container
Посмотрите контейнеры:
docker ps
Покажите также остановленные:
docker ps -a
PART 3 — Запускаем Nginx
docker run nginx
Откройте второй Terminal:
docker ps
Остановите:
docker stop CONTAINER_ID
Теперь запустим в background:
docker run -d nginx
-d означает detached mode — контейнер работает в фоне.
PART 4 — Даем контейнеру имя
docker run -d --name web-server nginx
Проверяем:
docker ps
Теперь вместо ID можно использовать имя:
docker stop web-server
Запустить снова:
docker start web-server
Перезапустить:
docker restart web-server
Удалить:
docker rm -f web-server
PART 5 — Docker Images
Посмотрите images:
docker images
Скачайте image вручную:
docker pull nginx
Скачайте конкретную версию:
docker pull nginx:alpine
Посмотрите:
docker images
Объясните студентам:
nginx = repository
alpine = tag
nginx:alpine = image + tag
latest — это просто tag. Он не означает автоматически «самая новая версия навсегда».
PART 6 — PORTS ⭐
Запустите:
docker run -d \
--name my-nginx \
-p 8080:80 \
nginx
Проверьте:
docker ps
Откройте:
http://localhost:8080
Объяснение:
Browser
↓
localhost:8080
↓
HOST PORT 8080
↓
CONTAINER PORT 80
↓
NGINX
Запомнить:
-p HOST_PORT:CONTAINER_PORT
PART 7 — Заходим внутрь Container
Посмотрите контейнер:
docker ps
Зайдите внутрь:
docker exec -it my-nginx sh
Теперь вы внутри контейнера.
Попробуйте:
pwd
ls
hostname
cat /etc/os-release
Посмотрите HTML:
ls /usr/share/nginx/html
cat /usr/share/nginx/html/index.html
Выход:
exit
PART 8 — Создаем собственное приложение
Создаем project:
mkdir docker-lab
cd docker-lab
Создаем:
touch index.html
Добавьте:
<!DOCTYPE html>
<html>
<head>
<title>JumpToTech Docker Lab</title>
</head>
<body>
<h1>Hello from Docker!</h1>
<h2>JumpToTech DevOps</h2>
<p>My first Docker application</p>
</body>
</html>
PART 9 — Dockerfile ⭐⭐⭐
Создайте:
touch Dockerfile
Добавьте:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
Объяснение:
FROM
Какой base image используем.
COPY
Копируем наши файлы внутрь image.
EXPOSE
Документирует порт, на котором приложение ожидает трафик. Сам по себе EXPOSE порт на host не публикует.
PART 10 — BUILD IMAGE
Построим:
docker build -t jumptotech-web:v1 .
Очень важно объяснить .:
.
=
current directory
=
Docker build context
Проверяем:
docker images
Должны увидеть:
jumptotech-web v1
PART 11 — Image → Container
docker run -d \
--name jumptotech-container \
-p 8080:80 \
jumptotech-web:v1
Проверяем:
docker ps
Открываем:
http://localhost:8080
🎉 Вы создали собственный Docker Image.
PART 12 — Docker Logs
docker logs jumptotech-container
Следить за логами:
docker logs -f jumptotech-container
Остановить просмотр:
Ctrl + C
Объясните:
Когда приложение не работает, одна из первых вещей DevOps engineer — посмотреть logs.
PART 13 — Inspect
docker inspect jumptotech-container
Здесь можно увидеть:
IP
Ports
Network
Mounts
Environment
Image
Configuration
Можно посмотреть IP:
docker inspect \
-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
jumptotech-container
PART 14 — Docker Processes
docker top jumptotech-container
Посмотрите использование ресурсов:
docker stats
Здесь увидите:
CPU
Memory
Network
Processes
Остановить:
Ctrl + C
PART 15 — Environment Variables
Запустите:
docker run --rm \
-e COMPANY=JumpToTech \
-e ENVIRONMENT=dev \
alpine env
Увидите:
COMPANY=JumpToTech
ENVIRONMENT=dev
В production environment variables часто используются для конфигурации:
DB_HOST
DB_PORT
APP_ENV
API_URL
Пароли и токены не следует hardcode-ить в Dockerfile или image.
PART 16 — Volumes ⭐⭐⭐
Контейнеры должны считаться временными.
Container deleted
↓
container writable data can disappear
Поэтому persistent data хранят отдельно.
Создаем volume:
docker volume create jumptotech-data
Посмотрите:
docker volume ls
Запустите:
docker run -d \
--name volume-demo \
-v jumptotech-data:/data \
alpine \
sh -c "echo 'Hello JumpToTech' > /data/student.txt && sleep 3600"
Проверяем:
docker exec volume-demo cat /data/student.txt
Удаляем container:
docker rm -f volume-demo
Создаем новый:
docker run --rm \
-v jumptotech-data:/data \
alpine \
cat /data/student.txt
Файл остался.
Это и есть идея:
Container
X deleted
Volume
✓ survives
PART 17 — Bind Mount
Создайте:
mkdir website
Создайте:
echo "<h1>Hello from Bind Mount</h1>" > website/index.html
Запустите:
docker run -d \
--name bind-demo \
-p 8081:80 \
-v "$(pwd)/website:/usr/share/nginx/html:ro" \
nginx
Откройте:
http://localhost:8081
Измените файл на компьютере:
echo "<h1>Docker is awesome!</h1>" > website/index.html
Refresh browser.
Изменение появится сразу.
PART 18 — Docker Network ⭐⭐⭐
Создаем network:
docker network create jumptotech-network
Проверяем:
docker network ls
Запускаем первый container:
docker run -d \
--name web1 \
--network jumptotech-network \
nginx
Второй:
docker run -it \
--rm \
--network jumptotech-network \
alpine sh
Внутри:
ping web1
Docker DNS на user-defined network позволяет обращаться к контейнеру по имени:
web1
Вместо запоминания IP.
Выход:
exit
PART 19 — Container-to-Container Communication
Представьте:
Frontend Container
↓
Backend Container
↓
Database Container
В Docker Network они могут обращаться друг к другу по DNS-именам:
frontend → backend
backend → database
Именно поэтому networking очень важен для microservices.
PART 20 — Dockerfile: основные инструкции
Студент должен знать:
FROM nginx:alpine
Base image.
WORKDIR /app
Рабочая директория.
COPY . .
Копирование файлов.
RUN npm install
Команда выполняется во время build.
ENV NODE_ENV=production
Environment variable.
EXPOSE 3000
Документирует container port.
CMD ["npm", "start"]
Default command при запуске container.
Также полезно знать:
ENTRYPOINT ["python", "app.py"]
PART 21 — RUN vs CMD ⭐
Очень важно.
RUN
выполняется при:
docker build
Например:
RUN npm install
А:
CMD
выполняется при:
docker run
Например:
CMD ["npm", "start"]
Запомнить:
RUN = BUILD TIME
CMD = RUN TIME
PART 22 — Docker Layers
Dockerfile:
FROM node:alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
Каждая инструкция может создавать или использовать layer/cache.
Поэтому порядок Dockerfile имеет значение.
Например, зависимости лучше копировать отдельно, чтобы Docker мог повторно использовать cache, когда package.json не изменился.
PART 23 — .dockerignore
Создайте:
touch .dockerignore
Пример:
.git
node_modules
.env
*.log
README.md
Зачем?
Чтобы ненужные или чувствительные файлы не попадали в build context/image.
PART 24 — Tags
Сейчас:
docker images
Создадим новый tag:
docker tag jumptotech-web:v1 jumptotech-web:v2
Проверяем:
docker images
Важно:
v1
v2
1.0.0
2026-09-10
git-sha
— примеры image tags.
В production лучше использовать конкретные immutable/versioned tags вместо того, чтобы полагаться только на latest.
PART 25 — Docker Registry
Архитектура:
Developer
↓
docker build
↓
Image
↓
docker push
↓
Registry
↓
docker pull
↓
Server / Kubernetes
Registry может быть:
Docker Hub
Amazon ECR
GitHub Container Registry
Google Artifact Registry
Azure Container Registry
PART 26 — Push Image
Пример Docker Hub:
docker login
Tag:
docker tag jumptotech-web:v1 USERNAME/jumptotech-web:v1
Push:
docker push USERNAME/jumptotech-web:v1
Теперь другой сервер может:
docker pull USERNAME/jumptotech-web:v1
PART 27 — AWS ECR ⭐
В реальном AWS workflow:
GitHub
↓
CI/CD
↓
docker build
↓
ECR
↓
EKS
Login:
aws ecr get-login-password --region us-east-1 | \
docker login \
--username AWS \
--password-stdin ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
Tag:
docker tag jumptotech-web:v1 \
ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/jumptotech-web:v1
Push:
docker push \
ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/jumptotech-web:v1
PART 28 — Docker Compose ⭐
Представьте, приложение состоит из:
Frontend
Backend
Database
Redis
Неудобно запускать всё отдельными docker run.
Поэтому для локального multi-container приложения используется Compose.
Создайте:
compose.yaml
Простой пример:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
redis:
image: redis:alpine
Запускаем:
docker compose up -d
Проверяем:
docker compose ps
Logs:
docker compose logs
Остановить и удалить созданные Compose containers/network:
docker compose down
PART 29 — Cleanup
Посмотрите всё:
docker ps -a
Images:
docker images
Volumes:
docker volume ls
Networks:
docker network ls
Удалить container:
docker rm -f CONTAINER_NAME
Удалить image:
docker rmi IMAGE_NAME
Удалить volume:
docker volume rm VOLUME_NAME
Удалить network:
docker network rm NETWORK_NAME
Очистка неиспользуемых объектов:
docker system prune
Будьте осторожны с более агрессивными prune-командами на рабочих машинах.
PART 30 — Troubleshooting ⭐⭐⭐
Это особенно важно для DevOps engineer.
Container не работает
docker ps -a
Посмотреть logs
docker logs CONTAINER
Посмотреть configuration
docker inspect CONTAINER
Зайти внутрь
docker exec -it CONTAINER sh
или, если установлен Bash:
docker exec -it CONTAINER bash
Проверить процессы
docker top CONTAINER
Проверить resources
docker stats
Проверить ports
docker port CONTAINER
Проверить networks
docker network ls
docker network inspect NETWORK
PART 31 — Что студент обязан знать после Docker
Я бы проверила каждого студента по этим вопросам:
| Topic | Student должен объяснить |
|---|---|
| Docker | зачем он нужен |
| Container | что это |
| Image | что это |
| Dockerfile | зачем нужен |
| Registry | где хранят images |
docker build |
создаёт image |
docker run |
создаёт/запускает container |
docker ps |
показывает containers |
docker images |
показывает images |
docker exec |
выполнить команду внутри container |
docker logs |
logs |
-p |
port mapping |
-v |
volume/bind mount |
-e |
environment variable |
| Network | communication |
| Volume | persistent data |
| Tag | версия image |
| Docker Compose | multi-container local apps |
| ECR | AWS container registry |
| Layers/cache | оптимизация build |
.dockerignore |
исключение файлов |
Финальное задание студентам 🔥
Не давайте им команды. Дайте только задачу:
Вы работаете DevOps Engineer в JumpToTech. Developer передал вам простой website.
Вам необходимо:
- Создать HTML application.
- Написать Dockerfile.
- Использовать Nginx.
- Построить image
jumptotech-web:v1. - Запустить container.
- Назвать container
jumptotech-prod. - Открыть приложение через port
8080. - Проверить container.
- Посмотреть logs.
- Зайти внутрь container.
- Найти
index.htmlвнутри container. - Создать volume.
- Создать custom Docker network.
- Объяснить разницу Image vs Container.
- Объяснить
8080:80. - Создать tag
v2. - Push image в registry.
- Остановить container.
- Удалить container.
- Снова получить image из registry и запустить приложение.
Главная схема урока
DOCKER
Developer Code
↓
Dockerfile
↓
docker build
↓
IMAGE
↓
TAG
↓
Registry
Docker Hub / ECR
↓
docker pull
↓
docker run
↓
CONTAINER
↙ ↓ ↘
PORT VOLUME NETWORK
↓
APPLICATION
↓
Kubernetes / EKS
Если студент самостоятельно выполнит финальное задание и сможет объяснить Dockerfile → Image → Registry → Container → Port → Volume → Network, у него уже будет хорошая практическая база Docker перед переходом к Kubernetes.
Top comments (0)