💻 Примеры: Dockerfile в действии

⚡ Минимальный пример: nginx со своей страницей

# my-nginx/Dockerfile
FROM nginx:1.27-alpine
COPY index.html /usr/share/nginx/html/
EXPOSE 80
# Терминал
docker build -t my-nginx ./my-nginx
docker run -d -p 8080:80 --name my-nginx my-nginx
# Открыть: http://localhost:8080

Пример 1: nginx с кастомной статической страницей

Создаём собственный образ nginx, который при запуске сразу отдаёт нашу HTML-страницу.

Структура проекта

# Терминал (PowerShell)
mkdir my-nginx
cd my-nginx
# Создаём два файла: index.html и Dockerfile

Шаг 1: HTML-страница

<!-- my-nginx/index.html -->
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Hello Docker!</title>
</head>
<body>
  <h1>Success! NGINX works in Docker!</h1>
  <p>Эта страница отдаётся из Docker-контейнера.</p>
</body>
</html>

Шаг 2: Dockerfile

# my-nginx/Dockerfile

# Используем официальный образ nginx на базе alpine (минимальный размер)
FROM nginx:1.27-alpine

# Копируем нашу страницу в директорию, откуда nginx раздаёт статику
COPY index.html /usr/share/nginx/html/

# Документируем порт (nginx слушает 80 по умолчанию)
EXPOSE 80

# nginx:alpine уже содержит CMD ["nginx", "-g", "daemon off;"] — переопределять не нужно

Шаг 3: Сборка образа

# Терминал (PowerShell) — запускаем из папки my-nginx
docker build -t my-nginx:1.0 .

# Проверяем, что образ создан
docker images | findstr my-nginx

Шаг 4: Запуск контейнера

# Терминал
docker run -d -p 8080:80 --name my-running-nginx my-nginx:1.0

# Проверка
docker ps
# Открыть в браузере: http://localhost:8080

Шаг 5: Остановка и очистка

# Терминал
docker stop my-running-nginx
docker rm my-running-nginx

Пример 2: Bash-скрипт с сохранением данных через volume

Пример из лекции: контейнер скачивает данные из API и сохраняет их в файл на хосте через volume.

Структура проекта

# Терминал (PowerShell)
mkdir fetch-data-app
cd fetch-data-app
# Создаём: fetch_data.sh, Dockerfile, .dockerignore

Bash-скрипт для скачивания данных

# fetch-data-app/fetch_data.sh
#!/bin/bash

URL="https://api.coindesk.com/v1/bpi/currentprice.json"
OUTPUT_FILE="/data/price.json"

echo "Downloading data from $URL..."
curl -o "$OUTPUT_FILE" "$URL"
echo "Data saved to $OUTPUT_FILE"

Dockerfile

# fetch-data-app/Dockerfile

FROM debian:stable-slim

# Устанавливаем curl и очищаем кеш в одном RUN — минимизируем слой
RUN apt-get update && apt-get install -y \
    curl \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Копируем скрипт и делаем его исполняемым
COPY fetch_data.sh /usr/local/bin/fetch_data.sh
RUN chmod +x /usr/local/bin/fetch_data.sh

# Рабочая директория
WORKDIR /usr/src/app

# Переменные окружения (можно переопределить при docker run -e)
ENV URL=https://api.coindesk.com/v1/bpi/currentprice.json
ENV OUTPUT_FILE=/data/price.json

# Точка монтирования для сохранения результатов
VOLUME ["/data"]

# Команда запуска
CMD ["/usr/local/bin/fetch_data.sh"]

.dockerignore

# fetch-data-app/.dockerignore
.git
.env
data/
*.log

Сборка и запуск

# Терминал (PowerShell)
docker build -t fetch-data-image .

# Создаём папку для данных на хосте
mkdir data

# Запуск: --rm удалит контейнер после остановки
# -v монтирует ./data в /data контейнера
docker run --rm -v "${PWD}/data:/data" fetch-data-image

# Проверяем результат
cat data/price.json
PowerShell vs bash: в PowerShell используйте ${PWD}/data:/data вместо $(pwd)/data:/data. Синтаксис отличается.

Пример 3: MySQL с именованным volume

Запускаем MySQL в Docker с постоянным хранилищем — данные сохраняются при перезапуске или удалении контейнера.

# Терминал
# Запуск MySQL 8.0 с именованным volume mysql-data
docker run -d \
  --name mysqlDB \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  -e MYSQL_DATABASE=myapp \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# Дождаться инициализации (~10–20 секунд)
docker logs -f mysqlDB
# Ctrl+C чтобы остановить слежение за логами

# Подключиться к MySQL
docker exec -it mysqlDB mysql -u root -p
# Ввести пароль: my-secret-pw
# Терминал — SQL внутри контейнера
SHOW DATABASES;
USE myapp;
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100));
INSERT INTO users (name) VALUES ('Alice');
SELECT * FROM users;
EXIT;
# Терминал — удалим и пересоздадим контейнер — данные сохранятся
docker stop mysqlDB
docker rm mysqlDB

docker run -d \
  --name mysqlDB \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# Снова подключаемся и проверяем — таблица и данные на месте
docker exec -it mysqlDB mysql -u root -p -e "SELECT * FROM myapp.users;"

Пример 4: PostgreSQL с volume

# Терминал
docker run -d \
  --name postgresDB \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=my-secret-pw \
  -e POSTGRES_DB=myapp \
  -e POSTGRES_USER=myuser \
  -v pg-data:/var/lib/postgresql/data \
  postgres:16-alpine

# Подключиться через psql
docker exec -it postgresDB psql -U myuser -d myapp
# Терминал — SQL внутри контейнера
CREATE TABLE products (id SERIAL PRIMARY KEY, name TEXT);
INSERT INTO products (name) VALUES ('Widget');
SELECT * FROM products;
\q
← К оглавлению урока