Docker на Ubuntu: Пълно ръководство за инсталиране и използване
Docker е платформа за контейнеризация с отворен код, която пакетира приложения и техните зависимости в изолирани, преносими единици, наречени контейнери. За разлика от виртуалните машини, контейнерите споделят ядрото на хост операционната система, което ги прави значително по-леки, по-бързи за стартиране и по-ефективни по отношение на ресурсите — критично разграничение за всеки, който изпълнява натоварвания в среда за VPS Хостинг, където изчислителните ресурси пряко влияят върху разходите и производителността.
Това ръководство обхваща пълния процес на инсталиране на Docker на Ubuntu 20.04, 22.04 и 24.04 LTS, включително укрепване след инсталацията, работни процеси с Docker Compose и производствено-релевантни командни шаблони, които повечето уроци пропускат.
Предварителни изисквания и системни изисквания
Преди да изпълните дори една команда, проверете следното:
- Версия на Ubuntu: 20.04 LTS (Focal), 22.04 LTS (Jammy) или 24.04 LTS (Noble). Командата `lsb_release -cs`, използвана по време на настройката на хранилището, автоматично ще открие вашето кодово име.
- Архитектура: `amd64`, `arm64` или `armhf` — всички се поддържат от официалното хранилище на Docker.
- Версия на ядрото: Docker изисква Linux ядро 3.10 или по-високо. Изпълнете `uname -r` за потвърждение.
- Потребителски привилегии: `sudo` или root достъп е задължителен за инсталиране и управление на демона.
- Дисково пространство: Минимум 2 GB свободно пространство на дяла, съдържащ `/var/lib/docker`, където Docker съхранява образи, контейнери, томове и кеш за изграждане. На производствени системи монтирайте тази директория на отделен дял или том.
Критична стъпка преди инсталацията: Ако преди това сте инсталирали Docker от хранилището `apt` по подразбиране на Ubuntu (пакетът `docker.io`), първо го премахнете, за да избегнете конфликти с официалните пакети Docker CE:
“`bash
sudo apt remove docker docker-engine docker.io containerd runc
“`
Стъпка 1: Актуализиране на системните пакети
Актуализирайте индекса на пакетите и инсталираните пакети до най-новите им версии, преди да добавите ново хранилище:
“`bash
sudo apt update
sudo apt upgrade -y
“`
Това гарантира, че резолверът на зависимости на `apt` работи спрямо актуални метаданни на пакетите и че библиотеките на базовата ви система не са остарели — честа причина за фини грешки по време на изпълнение при контейнеризирани приложения.
Стъпка 2: Инсталиране на Docker Engine от официалното хранилище
Хранилищата `apt` по подразбиране на Ubuntu съдържат пакет, наречен `docker.io`, поддържан от Canonical и обикновено изоставащ с няколко версии зад официалното издание на Docker. За производствена употреба винаги инсталирайте от собственото хранилище на Docker.
2.1 Инсталиране на транспортни и верификационни зависимости
“`bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y
“`
Защо `gnupg`? Започвайки с Ubuntu 22.04, `gpg` не винаги присъства по подразбиране. Включването му изрично предотвратява безшумното неуспешно импортиране на GPG ключа.
2.2 Добавяне на официалния GPG ключ на Docker
“`bash
sudo install -m 0755 -d /usr/share/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
“`
Стъпката `chmod a+r` често се пропуска в уроците, но е необходима на системи, където `apt` работи в контекст на ограничен потребител — без нея мениджърът на пакети не може да прочете ключодържателя и ще генерира грешка `NO_PUBKEY` по време на `apt update`.
2.3 Добавяне на стабилното хранилище на Docker
“`bash
echo
"deb [arch=$(dpkg –print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]
https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
“`
Заместването `arch=$(dpkg –print-architecture)` е от съществено значение на сървъри базирани на ARM. Твърдото кодиране на `amd64` тук е честа грешка, която причинява безшумни неуспехи при разрешаване на пакети на ARM инстанции.
2.4 Инсталиране на Docker Engine, CLI и плъгини
“`bash
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
“`
Разбивка на пакетите:
| Пакет | Роля |
|---|
| — | — |
|---|
| `docker-ce` | Демон на Docker Engine (`dockerd`) |
|---|
| `docker-ce-cli` | Клиентски CLI (команда `docker`) |
|---|
| `containerd.io` | Среда за изпълнение на контейнери на ниско ниво (съвместима с OCI) |
|---|
| `docker-buildx-plugin` | Разширени възможности за изграждане (мулти-платформа, BuildKit) |
|---|
| `docker-compose-plugin` | Compose V2 интегриран като плъгин за Docker CLI |
|---|
Бележка относно `containerd.io`: Това не е същото като пакета `containerd` в хранилището по подразбиране на Ubuntu. `containerd.io` на Docker е специфична, тествана версия на средата за изпълнение containerd. Смесването на двете е известна причина за неуспешно стартиране на демона.
Стъпка 3: Проверка на инсталацията
Потвърдете, че демонът е активен и е настроен да стартира при зареждане:
“`bash
sudo systemctl status docker
sudo systemctl enable docker
“`
Проверете инсталираната версия:
“`bash
sudo docker –version
sudo docker info
“`
`docker info` е по-информативен от `–version` самостоятелно — разкрива използвания драйвер за съхранение (обикновено `overlay2`), драйвера за cgroup (`systemd` срещу `cgroupfs`) и броя на CPU и паметта, до които Docker има достъп.
Изпълнете стандартния тест за проверка:
“`bash
sudo docker run hello-world
“`
При успешно изпълнение се отпечатва съобщение „Hello from Docker!” и се потвърждава, че демонът на Docker, изтеглянето на образ от Docker Hub и изпълнението на контейнер функционират правилно.
Стъпка 4: Конфигуриране на Docker за достъп без root права
По подразбиране Docker сокетът (`/var/run/docker.sock`) е собственост на `root` и групата `docker`. Всеки потребител, който не е в групата `docker`, трябва да използва `sudo` за всяка Docker команда.
“`bash
sudo usermod -aG docker $USER
“`
Приложете членството в групата без излизане от системата:
“`bash
newgrp docker
“`
Проверете:
“`bash
docker run hello-world
“`
Предупреждение за сигурност: Членството в групата `docker` е практически еквивалентно на `sudo` без парола. Потребител в групата `docker` може лесно да монтира файловата система на хоста в контейнер и да заобиколи всички контроли за достъп на ниво файлова система. На многопотребителски системи или споделени сървъри, помислете за използване на rootless Docker:
“`bash
dockerd-rootless-setuptool.sh install
“`
Режимът без root права изпълнява демона на Docker и контейнерите в непривилегировано потребителско пространство от имена, драстично намалявайки повърхността за атака. Това е препоръчителната конфигурация за всяка среда, в която множество потребители споделят един и същ хост.
Стъпка 5: Справочник с основни Docker команди
Управление на образи
“`bash
Pull a specific image version from Docker Hub
docker pull nginx:1.27-alpine
List locally cached images
docker images
Remove a specific image
docker rmi nginx:1.27-alpine
Remove all dangling (untagged) images to reclaim disk space
docker image prune
Remove all unused images (not just dangling)
docker image prune -a
“`
Производствен съвет: Винаги изтегляйте версионирани тагове (напр. `nginx:1.27-alpine`), а не `latest` в автоматизирани или производствени работни процеси. Тагът `latest` е променлив — може да сочи към различен образ след публикуване в регистъра, нарушавайки възпроизводимостта.
Жизнен цикъл на контейнера
“`bash
Run a container interactively with a pseudo-TTY
docker run -it ubuntu:22.04 /bin/bash
Run a container in detached mode with port mapping and a name
docker run -d -p 8080:80 –name my-nginx nginx:1.27-alpine
List running containers
docker ps
List all containers (including stopped)
docker ps -a
Stop a running container gracefully (SIGTERM, then SIGKILL after timeout)
docker stop my-nginx
Start a stopped container
docker start my-nginx
Remove a stopped container
docker rm my-nginx
Force-remove a running container (sends SIGKILL immediately)
docker rm -f my-nginx
View real-time logs
docker logs -f my-nginx
Execute a command inside a running container
docker exec -it my-nginx /bin/sh
“`
Инспекция на ресурси и система
“`bash
Display real-time resource usage statistics
docker stats
Inspect detailed container metadata (JSON)
docker inspect my-nginx
Display disk usage by Docker objects
docker system df
Remove all stopped containers, unused networks, dangling images, and build cache
docker system prune
“`
`docker system prune` е една от най-важните команди за поддръжка на дълго работещи сървъри. Без периодично почистване, кешът за изграждане на Docker и спрените контейнери могат да заемат десетки гигабайти на активен хост за разработка или CI.
Стъпка 6: Docker Compose — оркестрация на многоконтейнерни приложения
Docker Compose V2 (`docker-compose-plugin`, инсталиран по-рано) се извиква като `docker compose` (с интервал), а не като наследения `docker-compose` (с тире). И двата синтаксиса работят, ако имате инсталиран плъгина, но V2 е текущият стандарт.
6.1 Разбиране на структурата на Compose файла
Създайте директория за проекта и файл `compose.yml` (предпочитаното име на файла в Compose V2; `docker-compose.yml` остава поддържан за обратна съвместимост):
“`bash
mkdir ~/my-web-app && cd ~/my-web-app
nano compose.yml
“`
Реалистичен производствен пример с Nginx и бекенд услуга:
“`yaml
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
depends_on:
- app
restart: unless-stopped
app:
image: node:20-alpine
working_dir: /usr/src/app
volumes:
- ./app:/usr/src/app
command: node server.js
environment:
- NODE_ENV=production
restart: unless-stopped
“`
Обяснение на ключовите директиви на Compose:
- `restart: unless-stopped` — Контейнерът се рестартира автоматично след срив или рестартиране на системата, освен ако не е бил изрично спрян от оператора. Това е правилната политика за дълго работещи услуги; `always` ще рестартира дори умишлено спрени контейнери.
- `depends_on` — Контролира реда на стартиране, но не изчаква услугата да е *готова* (напр. база данни, приемаща връзки). За контрол на готовността използвайте `healthcheck` в комбинация с `condition: service_healthy`.
- `volumes` с `:ro` — Монтирането на конфигурационни файлове като само за четене предотвратява модифицирането на собствената конфигурация от компрометиран контейнерен процес.
6.2 Команди за работния процес на Compose
“`bash
Start all services in detached mode
docker compose up -d
View logs for all services
docker compose logs -f
View logs for a specific service
docker compose logs -f web
List running Compose services
docker compose ps
Scale a specific service to multiple replicas
docker compose up -d –scale app=3
Stop services without removing containers
docker compose stop
Stop and remove containers, networks, and volumes
docker compose down –volumes
Rebuild images before starting (useful after code changes)
docker compose up -d –build
“`
6.3 Проверка на работещата услуга
“`bash
curl -I http://localhost:8080
“`
Отговор `200 OK` потвърждава, че Nginx обслужва правилно. За услуги, работещи на отдалечен VPS Хостинг инстанс, заменете `localhost` с публичния IP адрес на вашия сървър и се уверете, че съответният порт е отворен в защитната стена (`ufw allow 8080/tcp`).
Стъпка 7: Основи на Docker мрежите
Разбирането на мрежовия модел на Docker е от съществено значение за изграждането на многоконтейнерни приложения, които комуникират сигурно.
Мрежови драйвери по подразбиране:
| Драйвер | Случай на употреба |
|---|
| — | — |
|---|
| `bridge` | По подразбиране за самостоятелни контейнери; изолирано мрежово пространство от имена на хоста |
|---|
| `host` | Контейнерът споделя мрежовия стек на хоста; максимална производителност, нулева изолация |
|---|
| `none` | Без мрежов достъп; полезен за пакетна обработка или натоварвания, чувствителни към сигурността |
|---|
| `overlay` | Многохостова мрежа за Docker Swarm клъстери |
|---|
| `macvlan` | Присвоява MAC адрес на контейнера; появява се като физическо устройство в мрежата |
|---|
Създаване и използване на персонализирана bridge мрежа:
“`bash
Create an isolated network
docker network create my-app-network
Run containers attached to the custom network
docker run -d –name db –network my-app-network postgres:16-alpine
docker run -d –name api –network my-app-network my-api-image
Containers on the same custom bridge network can resolve each other by name
Inside 'api', you can connect to 'db' using the hostname 'db'
“`
Персонализираните bridge мрежи осигуряват автоматично DNS разрешаване между контейнерите по име на контейнера. Мрежата `bridge` по подразбиране не го прави — това е критично разграничение, което причинява грешки при свързване, когато разработчиците приемат, че контейнерите в мрежата по подразбиране могат да се достигат един друг по име.
Стъпка 8: Постоянни данни с Docker томове
Контейнерите са ефемерни по своята същност. Всички данни, записани вътре в файловата система на контейнера, се губят при премахването му. За постоянно съхранение използвайте томове или bind монтирания.
“`bash
Create a named volume
docker volume create pgdata
Use the volume with a container
docker run -d
–name postgres-db
-e POSTGRES_PASSWORD=securepassword
-v pgdata:/var/lib/postgresql/data
postgres:16-alpine
List volumes
docker volume ls
Inspect a volume (shows mount point on host)
docker volume inspect pgdata
Remove unused volumes
docker volume prune
“`
Томове срещу bind монтирания:
| Функция | Именован том | Bind монтиране |
|---|
| — | — | — |
|---|
| Управляван от Docker | Да | Не |
|---|
| Изисква се хост път | Не | Да |
|---|
| Преносим между хостове | Да (с драйвери за томове) | Не |
|---|
| Най-подходящ за | Данни на бази данни, състояние на приложения | Код за разработка, конфигурационни файлове |
|---|
| Механизъм за архивиране | `docker run –volumes-from` | Стандартни инструменти за файлова система |
|---|
Стъпка 9: Поддържане на Docker актуален
Официалното хранилище на Docker обработва актуализациите чрез стандартния механизъм `apt`:
“`bash
sudo apt update
sudo apt upgrade -y
“`
За актуализиране само на пакети, свързани с Docker, без надграждане на цялата система:
“`bash
sudo apt install –only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
“`
Проверете бележките за изданието на Docker преди надграждания на основни версии, особено за промени в драйвера за съхранение, обработката на версията на cgroup или остарели версии на API, които могат да засегнат съществуващите файлове `compose.yml`.
Docker срещу алтернативни подходи за контейнеризация
| Функция | Docker Engine | Podman | LXC/LXD | containerd (самостоятелен) |
|---|
| — | — | — | — | — |
|---|
| Архитектура на демона | Централизиран демон | Без демон | Базиран на демон | Базиран на демон |
|---|
| Поддръжка без root права | Да (v20+) | Вградена | Ограничена | Да |
|---|
| Поддръжка на Docker Compose | Вградена | Чрез `podman-compose` | Не | Не |
|---|
| OCI съответствие | Да | Да | Не (LXC формат) | Да |
|---|
| Интеграция с Kubernetes | Чрез CRI-dockerd shim | Вграден CRI | Не | Вграден CRI |
|---|
| Поддръжка на Windows/macOS | Docker Desktop | Ограничена | Не | Не |
|---|
| Най-подходящ за | Обща разработка и производство | Фокусиран върху сигурността, без root права | Системни контейнери, виртуални машини | Kubernetes възли |
|---|
За екипи, изпълняващи контейнеризирани натоварвания в мащаб на bare metal, средата Dedicated Servers ви дава пълен контрол върху параметрите на ядрото, планирането на I/O за съхранение и мрежовата конфигурация — всички от които пряко влияят върху плътността на контейнерите и производителността.
Контролен списък за укрепване на производствената среда
Преди да стартирате Docker в производствена среда, адресирайте следното:
Конфигурация на демона (`/etc/docker/daemon.json`):
“`json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"userns-remap": "default",
"live-restore": true,
"no-new-privileges": true
}
“`
- `log-opts` с `max-size` и `max-file`: Без ротация на логовете, JSON лог файловете на Docker ще запълнят диска ви. Това е една от най-честите причини за неочаквани прекъсвания на сървъри с контейнеризирани хостове.
- `userns-remap: "default"`: Активира преназначаване на потребителски пространства от имена, така че root в контейнера (UID 0) да се съпостави с непривилегирован UID на хоста.
- `live-restore: true`: Позволява на контейнерите да продължат да работят, ако демонът на Docker се срине или бъде рестартиран по време на надграждане — критично за поддръжка без прекъсване.
- `no-new-privileges: true`: Предотвратява получаването на допълнителни привилегии от контейнерни процеси чрез двоични файлове `setuid` или `setgid`.
Мрежови съображения и защитна стена:
Docker манипулира `iptables` директно и по подразбиране заобикаля правилата на `ufw`. Контейнер с публикуван порт (`-p 8080:80`) ще бъде достъпен от интернет дори ако `ufw deny 8080` е зададен. За да наложите правилата на `ufw` над манипулацията на `iptables` от Docker, добавете `"iptables": false` към `daemon.json` и управлявайте маршрутизирането ръчно, или използвайте `–network host` на Docker с изрични правила `ufw`.
За проекти, изискващи HTTPS терминиране, сдвоете контейнеризираното си приложение с правилно конфигуриран обратен прокси (Nginx или Traefik) и валиден сертификат. SSL Сертификатите са предпоставка за всяка производствена уеб услуга, работеща зад контейнеризиран стек.
Ако вашето натоварване включва извод за машинно обучение, обслужване на модели или GPU-ускорена обработка на данни в контейнери, NVIDIA Container Toolkit се интегрира директно с Docker Engine. GPU Хостингът осигурява необходимия хардуер за тези натоварвания.
За екипи, управляващи множество проекти с уеб-базирано управление на контейнери, VPS с cPanel предлага управлявана среда с контролен панел, която може да допълни базираните на Docker внедрявания за по-прости стекове от приложения.
Ключови технически изводи и матрица за вземане на решения
Кога да използвате Docker на VPS срещу dedicated сървър:
- Използвайте VPS за среди за разработка, тестване и производствени натоварвания с ниско до средно натоварване, където плътността на контейнерите е 10–50 контейнера.
- Използвайте dedicated сървър, когато плътността на контейнерите надвишава 50 инстанции, когато се нуждаете от предвидима I/O производителност (без ефект на шумен съсед) или когато настройката на параметрите на ядрото (`sysctl`) е необходима за вашето натоварване.
Оперативен контролен списък преди пускане в производство:
- Конфигурирайте ротация на логовете в `daemon.json` (`max-size`, `max-file`)
- Активирайте `live-restore` за оцеляване при рестартиране на демона без прекъсване на контейнерите
- Използвайте именувани томове, а не bind монтирания, за данни на услуги със състояние
- Фиксирайте версиите на образите във всички файлове `compose.yml` — никога не използвайте `latest` в производство
- Активирайте `userns-remap` или стартирайте rootless Docker на многопотребителски хостове
- Проверете правилата на `iptables` след инсталацията на Docker, за да потвърдите, че политиката на защитната стена не е заобиколена
- Задайте `restart: unless-stopped` на всички дълго работещи услуги
- Изпълнявайте `docker system prune` по планирано cron задание, за да предотвратите изчерпване на диска
- Използвайте персонализирани bridge мрежи за всяка комуникация между контейнери — никога не разчитайте на bridge мрежата по подразбиране за откриване на услуги
Често задавани въпроси
Използва ли Docker на Ubuntu `systemd` или `cgroupfs` като cgroup драйвер по подразбиране?
От Docker Engine 20.10, cgroup драйверът по подразбиране на системи базирани на `systemd` (включително всички съвременни Ubuntu LTS издания) е `systemd`. Това съответства на изискванията на Kubernetes и избягва нестабилността, причинена от едновременното изпълнение на два мениджъра на cgroup. Можете да проверите с `docker info | grep -i cgroup`.
Каква е разликата между `docker compose down` и `docker compose stop`?
`docker compose stop` спира работещите контейнери, но ги запазва заедно с техните асоциирани мрежи. `docker compose down` спира контейнерите и след това ги премахва заедно с мрежите, създадени от Compose. Добавянето на `–volumes` към `down` също премахва именуваните томове, дефинирани в Compose файла — използвайте този флаг с внимание в производство, тъй като той окончателно изтрива постоянните данни.
Защо Docker заобикаля правилата на защитната стена `ufw` на Ubuntu?
Docker вмъква собствени правила `iptables` в веригите `DOCKER` и `DOCKER-USER`, които се оценяват преди правилата на веригата `INPUT` на `ufw`. Това означава, че порт, публикуван с `-p`, е достъпен от интернет независимо от политиката на `ufw`. Правилното решение е да добавите правила директно към веригата `DOCKER-USER` или да обвържете публикуваните портове с конкретен интерфейс (напр. `-p 127.0.0.1:8080:80`), когато външен достъп не е необходим.
Как да ограничя CPU и паметта, които може да консумира Docker контейнер?
Използвайте флагове за ограничаване на ресурсите по време на изпълнение: `docker run –memory="512m" –cpus="1.5" my-image`. В Compose задайте тези стойности под ключа `deploy.resources` (Compose V2) или ключовете от най-горно ниво `mem_limit` и `cpus`. Без ограничения, един неконтролиран контейнер може да изчерпи ресурсите на хоста и да срине всички останали контейнери на същия хост.
Мога ли да стартирам Docker вътре в Docker контейнер (Docker-in-Docker)?
Да, но това е силно обезкуражено за производствена употреба. Честият шаблон за CI конвейери е монтирането на хост Docker сокета (`-v /var/run/docker.sock:/var/run/docker.sock`) в CI контейнера, което дава на контейнера пълен контрол върху демона на Docker на хоста — значителен риск за сигурността. По-безопасна алтернатива е използването на флага `–allow security.insecure` на BuildKit или специализирани инструменти като Kaniko или Buildah, които изграждат OCI образи без нужда от Docker демон.
