Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як запустити контейнер з Docker image?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`docker run`** створює і стартує container з image в одному кроці. Шість флагів покривають майже кожен реальний кейс: `-d` (фон), `--name`, `-p` (публікація порту), `-v` (mount), `-e` (env-змінна), `--rm` (авто-очищення). ```bash docker run -d \ --name web \ -p 8080:80 \ -v webdata:/usr/share/nginx/html \ -e NGINX_HOST=example.com \ --restart=unless-stopped \ nginx:1.27-alpine ``` **Головне:** `docker run` = `docker create` + `docker start`. Image йде останнім; усе до нього це флаги. Усе після імені image перевизначає `CMD` з image.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`docker run`** це найвживаніша команда у всьому Docker CLI. Вона тягне image, якщо треба, створює container і стартує його, усе одним махом. Знання шести флагів, що з'являються у кожній прод-команді, це і є більшість того, що значить «використовувати Docker». ## Теорія ### TL;DR - Анатомія: `docker run [FLAGS] IMAGE[:TAG] [COMMAND] [ARGS...]` - Image йде між флагами і будь-яким override команди. Усе після image замінює `CMD` image. - Шість флагів покривають 90% кейсів: `-d`, `--name`, `-p`, `-v`, `-e`, `--rm`. - `docker run` = `docker pull` (якщо нема) + `docker create` + `docker start`. Три операції в одній команді. - Бери `--rm` для одноразових команд (авто-cleanup на виході). Бери `-d` + `--restart` для довгоживучих сервісів. ### Швидкий приклад ```bash # Мінімум: pull і run $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world Digest: sha256:9f8e7d6c... Status: Downloaded newer image for hello-world:latest Hello from Docker! ``` Daemon помітив, що image нема, стягнув з Docker Hub, потім запустив. Одна команда, три операції. ### Шість флагів, які ти будеш використовувати щодня #### `-d` / `--detach` — запуск у фоні ```bash docker run -d nginx:1.27-alpine # Повертає одразу container ID; container продовжує крутитися. ``` Без `-d` CLI стрімить логи і виходить, коли container виходить. З `-d` ти миттєво повертаєшся у shell. #### `--name` — задай йому ім'я ```bash docker run -d --name web nginx:1.27-alpine # Тепер можна: docker stop web, docker logs web тощо. # Без --name Docker дає випадкове ім'я типу "sleepy_einstein". ``` #### `-p` / `--publish` — публікувати порти ```bash # Формат: HOST_PORT:CONTAINER_PORT docker run -d -p 8080:80 nginx:1.27-alpine # Порт 80 container доступний на http://localhost:8080 # Прив'язатися до конкретного host-інтерфейсу docker run -d -p 127.0.0.1:8080:80 nginx:1.27-alpine # Тільки loopback, не публічна мережа # Випадковий host-порт (авто-присвоєний) docker run -d -p 80 nginx:1.27-alpine # docker port <name>, щоб дізнатися, який host-порт обрано ``` Без `-p` container ізольований на своїй мережі: доступний з інших container на тій самій мережі, але не з host. #### `-v` / `--volume` — монтувати сховище ```bash # Named volume docker run -d -v pgdata:/var/lib/postgresql/data postgres:16 # Bind mount (конкретний host-шлях) docker run -d -v /home/me/site:/usr/share/nginx/html nginx:1.27-alpine # Read-only mount docker run -d -v ./conf:/etc/myapp:ro myapp ``` Named volume для персистентного стану, bind mount для live-reload dev або конкретних host-шляхів. #### `-e` / `--env` — env-змінні ```bash # Одна змінна docker run -e POSTGRES_PASSWORD=devpass postgres:16 # Пробросити з shell docker run -e API_KEY postgres:16 # З файлу docker run --env-file .env postgres:16 ``` Не передавай secret через `-e` у проді, вони показуються у `docker inspect`, image-history і process listing. Бери Swarm secret, BuildKit secret mount або external secret manager. #### `--rm` — авто-cleanup на виході ```bash # Одноразова команда, container зникає по завершенні docker run --rm -it alpine sh # Коли вийдеш з shell, container видаляється (без orphan). ``` Робить ad-hoc команди схожими на запуск локальних скриптів. Без `--rm` кожен exited container накопичується, поки не `docker rm` його. ### Флаги для довгоживучих сервісів ```bash --restart=no # дефолт: не рестартити --restart=on-failure # рестартити лише якщо exit code != 0 --restart=always # рестартити завжди (навіть при рестарті daemon) --restart=unless-stopped # як 'always', але поважає ручний docker stop ``` Для прод-сервісів зазвичай `--restart=unless-stopped`. ### Все разом: реалістична команда ```bash docker run -d \ --name api \ --restart=unless-stopped \ -p 3000:3000 \ -v api_uploads:/app/uploads \ -v ./api/.env:/app/.env:ro \ -e NODE_ENV=production \ --memory=512m \ --cpus=0.5 \ --health-cmd='curl -f http://localhost:3000/health' \ --health-interval=30s \ myapp:1.0 ``` Це по суті як виглядає прод single-host deploy, перш ніж ти переходиш на Compose, Swarm або Kubernetes. ### Перевизначення `CMD` image Усе після імені image замінює дефолтну команду image: ```bash # Дефолтний CMD image (зазвичай сервіс) docker run nginx:1.27-alpine # Перевизначити CMD одноразовою командою docker run nginx:1.27-alpine sh -c 'nginx -V' # Запустить nginx -V і вийде, замість того щоб запускати daemon. # Кинутися у shell для дебагу docker run -it nginx:1.27-alpine sh ``` Якщо image має `ENTRYPOINT`, твої trailing args стають його аргументами. Використовуй `--entrypoint /bin/sh`, щоб повністю перевизначити entrypoint при дебагу. ### Типові помилки **Забути `-d` для сервісу** ```bash $ docker run nginx:1.27-alpine # Термінал висить, стрімить nginx-логи. # Ctrl+C зупиняє container. ``` Для чого-небудь крім одноразової команди зазвичай хочеш `-d`. **Неправильний напрямок порту у `-p`** ```bash # НЕПРАВИЛЬНО: думає, що 80 на host, 8080 у container docker run -p 80:8080 nginx:1.27-alpine # Ніщо не слухає порт 8080 у container; на host:80 connection refused. # ПРАВИЛЬНО: HOST:CONTAINER docker run -p 8080:80 nginx:1.27-alpine ``` Порядок: host перший, container другий. Поширений gotcha. **Класти флаги після імені image** ```bash # НЕПРАВИЛЬНО: -p трактується як аргумент для nginx docker run nginx:1.27-alpine -p 8080:80 # ПРАВИЛЬНО: флаги перед image docker run -p 8080:80 nginx:1.27-alpine ``` Docker припиняє парсити флаги на імені image. Усе після це команда для container, не для `docker run`. **Запускати інтерактив без `-it`** ```bash # НЕПРАВИЛЬНО: shell виходить одразу, бо нема TTY docker run alpine sh # ПРАВИЛЬНО: -i тримає stdin відкритим, -t виділяє TTY docker run -it alpine sh ``` `-it` (або `-i -t`) це магічна формула для інтерактивних сесій. ### Реальне застосування - **Локальна розробка:** `docker run --rm -it -v $PWD:/work node:22 npm test` — одноразовий container, монтує поточну директорію, проганяє тести, зникає. - **Staging/single-host deploy:** довга форма `docker run -d --name api --restart=unless-stopped ...`, часто загорнута у shell-скрипт або Compose-файл. - **CI/CD:** `docker run --rm myapp:test npm run test` дає exit code, який CI використовує для pass/fail. - **Одноразові DB-міграції:** `docker run --rm --network mynet -e DATABASE_URL=... migrator:1.0` запускається і зникає. ### Питання для поглиблення **Q:** Яка різниця між `docker run` і `docker create`? **A:** `create` виділяє container, але не стартує; треба `docker start` після. `run` робить обидва. `create` корисний, коли хочеш налаштувати container і запустити пізніше, або подивитися його config (`docker inspect`) перед стартом. **Q:** Як виконати команду в існуючому container замість запуску нового? **A:** `docker exec`. `docker run` завжди створює новий container; `docker exec` запускає команду у вже запущеному. Для shell у існуючий: `docker exec -it <name> sh`. **Q:** Чому мій інтерактивний `docker run -it` одразу виходить? **A:** Скоріш за все, бо `ENTRYPOINT` або `CMD` image це не shell. Спробуй `docker run -it --entrypoint sh <image>`, щоб форсувати shell. Або глянь у docs image, яка правильна команда. **Q:** Чи можу я запустити container, не давши йому ім'я? **A:** Так, Docker генерує випадкове (`musing_einstein`, `crazy_curie`). Нормально для одноразових `--rm` команд. Для чогось, на що будеш посилатися пізніше (логи, exec, stop), `--name` економить набирання. **Q:** (Senior) Чому у проді можеш уникати `docker run` і брати Compose або Kubernetes? **A:** Довга `docker run` команда це імперативний стан, що живе у чийсь shell-history. Compose робить його декларативним (у `compose.yaml`), version-controllable, відтворюваним. Kubernetes іде далі (multi-host, self-healing, rolling updates). Для одноразового сервісу `docker run` нормально. Для чого-небудь, що будеш redeploy'ити, декларативно перемагає імперативно. ## Приклади ### Локальний one-off: швидкий тест ```bash $ docker run --rm -it \ -v $PWD:/work \ -w /work \ node:22-alpine \ npm test # Тести крутяться всередині container, вивід стрімить у термінал, # container видаляється по завершенні. Лептоп лишається чистим. ``` `--rm`, `-it`, `-v $PWD:/work`, `-w /work`: чотири флаги, що роблять container схожим на локальний скрипт. ### Production-style web-сервіс ```bash $ docker run -d \ --name web \ --restart=unless-stopped \ -p 80:80 -p 443:443 \ -v web_certs:/etc/nginx/certs \ -v ./nginx.conf:/etc/nginx/nginx.conf:ro \ --memory=256m \ nginx:1.27-alpine $ docker ps --filter name=web CONTAINER ID IMAGE STATUS PORTS NAMES f7c2a9e1b8d4 nginx:1.27-alpine Up 3 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp web ``` Detached, named, restart-on-reboot, два порти опубліковано, серти у named volume, конфіг bind-mounted read-only, ліміт пам'яті. ### Перевизначення CMD image для дебагу ```bash # Дефолтний CMD image стартує postgres. Хочемо shell. $ docker run --rm -it postgres:16 bash # Або скіпни entrypoint повністю $ docker run --rm -it --entrypoint sh postgres:16 ``` Корисно, коли старт image падає і треба полазити всередині.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.