В этой статье мы расскажем про базовые техники работы с Docker, а также погрузим читателя в основы докеризации приложений.
Предполагается, что читатель что-то слышал про Docker и хотел бы начать знакомство с технологией. Мы постараемся упростить этот процесс.
Введение
Docker — это платформа, позволяющая запускать приложения в изолированных контейнерах. Контейнеры обеспечивают приложениям стабильную и предсказуемую среду, где бы они ни запускались, будь то компьютер разработчика/сервер/облако/кластер Kubernetes.
Docker обеспечивает повторяемость и консистентность проекта. Благодаря этому разработчики могут сосредоточиться непосредственно на разработке приложения, не беспокоясь о проблемах совместимости и настройке окружения.
Чтобы понять, как работает Docker, нужно иметь представление о его двух основных единицах: образ и контейнер.
Контейнеры
Контейнеры — это легковесные, изолированные среды выполнения, внутри которых работают приложения.
В отличие от виртуальных машин, контейнеры используют общее ядро операционной системы, что делает их менее затратными с точки зрения ресурсов. Это позволяет запускать больше контейнеров на одном сервере по сравнению с количеством виртуальных машин.
Контейнеры предоставляют множество преимуществ, включая:
Изоляцию. Каждое приложение (в идеале) работает в своей собственной, изолированной среде внутри контейнера;
Повторяемость. Docker гарантирует, что контейнер, который работает на машине разработчика, будет также работать и на сервере, без каких-либо неожиданностей;
Простоту доставки. Образы могут быть легко перенесены между различными окружениями, будь то локальное окружение, тестовые сервера или облачная инфраструктура.
Образы
Образ Docker — это статичное описание содержимого контейнера, включающее в себя все зависимости, настройки окружения, библиотеки и бинарные файлы, необходимые для выполнения приложения. Можно сказать, что образ является готовым к использованию шаблоном для создания контейнеров.
Образы часто создаются на базе других образов. Это происходит благодаря системе слоев, которая позволяет создавать и сохранять изменения поверх базового образа.
Например, вы можете взять официальный образ Go и добавить в него свой код, получив новый образ, готовый к развертыванию (подробнее в разделе о Dockerfile).
Запуск первого контейнера с Docker
Предположим, что вы уже установили Docker CLI или Docker Desktop для своей системы и, возможно, попытались запустить свой первый hello world контейнер командой docker run hello-world.
Разберем подробнее, какие действия выполняет эта команда:
Docker ищет образ hello-world в локальном хранилище. Если образ не найдется, то Docker скачает его с Docker Hub;
Далее Docker создает контейнер на основе этого образа и запускает его;
Контейнер выполняет скрипт, который выводит на экран приветственное сообщение и завершает работу.
Весь описанный процесс можно наблюдать в терминале, в котором выполняется команда. Если все прошло успешно, вы увидите сообщение, подтверждающее успешный запуск контейнера и его работу:
Hello from Docker!
This message shows that your installation appears to be working correctly.
Основные команды
Docker предоставляет широкие возможности для управления контейнерами и образами с помощью команд CLI. В этом разделе мы рассмотрим основные команды Docker, которые помогут вам эффективно управлять контейнерами.
Запуск контейнера — это основное действие, которое вы будете выполнять в Docker. Мы уже запускали контейнер hello-world в предыдущем разделе.
Теперь попробуем запустить более сложное приложение. Например, официальный образ операционной системы Ubuntu: docker run -it ubuntu bash
Эта команда делает следующее:
флаг --it объединяет две опции: -i (interactive) и -t (tty)
-i (--interactive) означает, что запускаемый контейнер будет получать стандартный поток ввода с хоста и направлять его в приложение, работающее в контейнере. По-умолчанию контейнеры стартуют изолированно, и stdin запущенного приложения не имеет связи с внешним миром.
-t (--tty) указывает докеру создать для запущенного приложения псевдотерминал, что позволит удобно работать с ним из вашего терминала.
ubuntu — название образа, который мы запускаем Ubuntu;
bash — команда внутри контейнера ubuntu.
Чтобы остановить контейнер, используется команда: docker stop <container_id>
Где <container_id> — это идентификатор контейнера, который вы хотите остановить. Вы можете определить идентификатор контейнера с помощью следующей команды: docker ps. Эта команда выводит список запущенных контейнеров вместе с их идентификаторами.
Если вам нужно перезапустить контейнер, используйте команду docker restart: docker restart <container_id>. ID контейнера можно получить из вывода команды ps, однако большинство команд, работающих с ID контейнеров, могут работать и с названиями.
Чтобы удалить контейнер, необходимо сначала остановить его, а затем использовать команду rm: docker rm <container_id>
Для одновременной остановки и удаления контейнера можно использовать флаг -f (force): docker rm -f <container_id>
Управление образами Docker
Для загрузки образа без его запуска можно использовать команду pull, например, docker pull ubuntu. Эта команда загрузит в локальное хранилище последний (latest) образ Ubuntu, однако при необходимости можно указать конкретную версию образа: docker pull ubuntu:20.04
Чтобы увидеть все доступные на вашем компьютере образы, используйте команду: docker images
Для удаления образа используйте команду docker rmi (remove image): docker rmi <image_id>
Получить идентификатор образа можно с помощью команды docker images.
Dockerfile и образы Docker
В этом разделе мы подробно рассмотрим, что такое образы Docker, их роль в контейнеризации, а также процесс создания собственных образов с помощью Dockerfile. Мы также разберем контекст Dockerfile и многоступенчатую сборку.
Что такое образы Docker?
Образ Docker — это лёгкий, автономный и исполняемый пакет, включающий всё необходимое для запуска части программного обеспечения, включая код, среды выполнения, библиотеки и системные зависимости. Образы Docker служат шаблоном для создания контейнеров. Образы описываются с помощью Dockerfile.
Dockerfile — это текстовый файл специального формата, содержащий команды для сборки Docker-образа. Эти команды описывают шаги, необходимые для установки зависимостей и конфигурации вашего приложения с учетом контекста приложения.
Контекст Dockerfile — это набор файлов, которые будут отправлены на Docker daemon для сборки образа. Часто это директория, в которой находится сам Dockerfile и любые другие файлы, необходимые для сборки (в основном, код).
Простой пример Dockerfile
Рассмотрим простой пример Dockerfile для приложения на Node.js:
# Указываем базовый образ
FROM node:14
# Устанавливаем рабочую директорию внутри будущего контейнера
WORKDIR /app
# Копируем package.json и package-lock.json в /app (./ из-за WORKDIR)
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install
# Копируем файлы приложения (с хоста (контекст) в образ (/app))
COPY . .
# Открываем порт
EXPOSE 3000
# Запускаем приложение
CMD ["node", "server.js"]
Теперь можно попробовать собрать приложение: docker build -t node-app:latest
-t указывает docker собрать образ с тегом
node-app — название образа
latest — тег
После того, как Docker завершит сборку успехом, можно запустить приложение: docker run node-app
Крайне важное замечание про Dockerfile: каждая команда создает свой собственный слой образа. Из-за этого образы могут раздуваться до огромных размеров. Для того, чтобы этого не происходило, существует поэтапная сборка.
Поэтапная (multistage) сборка
multistage -сборка позволяет уменьшить размер итоговых образов, используя несколько команд FROM.
В качестве примера рассмотрим сборку простого Go-приложения:
# BUILD STAGE
FROM golang:1.16 AS build
WORKDIR /go/src/app
COPY . .
RUN go build -o myapp
# RUN STAGE
FROM alpine:latest
WORKDIR /root/
COPY --from=build /go/src/app/myapp .
CMD ["./myapp"]
В итоговый образ попадет только то, что было в образе alpine плюс исполняемый файл myapp.
Docker Hub, репозитории образов
Docker Hub — это репозиторий, который предоставляет разработчикам возможность легко обмениваться и управлять контейнерными образами.
С помощью Docker Hub вы можете:
- Искать и загружать публичные образы, предоставляемые сообществом;
- Создавать и делиться собственными изображениями;
- Управлять автоматическими сборками и интеграциями с системой контроля версий.
Docker Hub предлагает огромное количество публичных образов, таких как образы операционных систем, баз данных, веб-серверов и различных приложений. Использование этих образов позволяет экономить время и усилия при настройке и развертывании приложений.
Один из основных процессов работы с Docker Hub — это загрузка (pull) и выгрузка (push) образов. Начнем с того, как загрузить образ из Docker Hub.
Команда docker pull позволяет скачать нужный образ на локальную машину.
docker pull ubuntu:latest
Эта команда загрузит последнюю версию образа Ubuntu. После загрузки образа, вы можете запустить контейнер на его основе:
docker run -it ubuntu:latest /bin/bash
Для выгрузки образов, сначала необходимо создать аккаунт на Docker Hub и авторизоваться в командной строке: docker login
После успешной авторизации, вы можете загрузить собственный образ. Сначала убедитесь, что image отмечен тегом:
docker tag <image_id> your_dockerhub_username/repo_name:tag
Теперь можно загрузить образ: docker push
your_dockerhub_username/repo_name:tag
Docker Hub предоставляет множество готовых образов для популярных инструментов, которые могут значительно упростить разработку и развертывание ваших проектов.
Рассмотрим несколько из них:
Alpine Linux (alpine) — это крошечный дистрибутив Linux на основе BusyBox, его образ имеет размер всего 5 МБ;
PHP (php-cli, php-fpm) — образы для интерпретатора php, включает все необходимое для разработки под этот язык;
MySQL (mysql) — здесь понятно, всем известная БД;
NGINX (nginx) — пригодится для создания обратного прокси-сервера;
Redis (redis) — высокопроизводительная in-memory база данных, используемая для кеширования и управления сессиями;
Node.js (node) — среда выполнения JavaScript, необходимая для запуска серверного кода на базе Node.js.
Более того, почти у каждого популярного образа есть alpine- и slim-версии, отличающиеся от обычных базой в виде alpine, а также уменьшенным объемом (обычно, slim-версии не включают в себя инструменты для сборки, а предназначены только для исполнения).
Любой образ из Docker Hub можно подтянуть с помощью команды docker pulll. Использование готовых образов сокращает время на настройку окружения.
Также стоит отметить, что Docker Hub — не единственный репозиторий образов.
Так, Gitlab (по крайней мере, self-hosted-версия) предлагает вам свое хранилище, которое очень удобно использовать в связке с Gitlab CI.
Сети
Работа с сетями — это одна из ключевых составляющих контейнеризации в Docker. Отсутствие настройки сетевого взаимодействия контейнеров может привести к проблемам с доступом к вашим сервисам.
Docker предоставляет несколько драйверов сетевого взаимодействия, из которых наиболее распространённые — bridge, host и overlay.
Bridge
Этот сетевой режим используется по умолчанию. В нем создается виртуальный мост (bridge), который позволяет контейнерам общаться друг с другом и с хост-машиной.
При запуске контейнера создается виртуальный интерфейс и подключается к мосту, предоставляя контейнерам IP-адреса из определенного диапазона. Bridge-сеть позволяет изолировать контейнеры от других сетевых интерфейсов хост-машины.
Для подключения контейнера к сети, укажите имя сети при запуске контейнера с использованием флага --network
docker network create --driver bridge app_network
docker run -d --network app_network --name app nginx
Host
В этом режиме контейнер использует сетевой стек хост-машины. Это означает, что контейнер и хост имеют общий IP-адрес и порты. Host-сеть полезна для уменьшения сетевой задержки, однако она уменьшает изоляцию между контейнером и хостом.
docker run -d --network host nginx
Overlay
Этот режим в основном используется в кластерных средах и Docker Swarm.
Overlay-сети позволяют контейнерам, работающим на разных физических или виртуальных машинах, общаться друг с другом так, будто они находятся на одной сети. Это достигается путем создания распределенной сети поверх существующей физической инфраструктуры.
docker network create --driver overlay --subnet 10.0.9.0/24 my_overlay_network
Коммуникация между контейнерами является ключевым аспектом для микросервисной архитектуры и распределенных систем. В Docker вы можете легко настроить взаимодействие между контейнерами, используя созданные вами сети.
После подключения к одной сети, контейнеры могут общаться друг с другом по именам хоста: docker exec container2 ping container1. Это становится возможным благодаря встроенному DNS-сервису Docker.
Для списка доступных сетей используйте команду: docker network ls
Для отключения контейнера от сети используйте команду: docker network disconnect <network_name> <container_id>
Чтобы удалить сеть, используйте команду: docker network rm <network_name>
Docker Volumes и связывание контейнера с файловой системой хоста (bind mounts)
Volumes и bind mounts — два ключевых механизма для работы с данными в контейнерах. Они необходимы, чтобы эффективно управлять данными, обеспечивать их сохранность и доступность.
Docker volumes существуют, чтобы хранить данные отдельно от контейнера. Даже в случае, если контейнер удалится, данные, хранящиеся в volume, останутся нетронутыми, что важно, когда проект уже развернут на площадке.
Bind Mounts немного отличаются от volumes. Этот подход представляет собой простое монтирование директорий с хоста в директории внутри контейнера. Это позволяет контейнерам иметь прямой доступ к данным на хосте, что удобно для среды разработки и тестирования.
Когда вы используете bind mounts, Docker не управляет содержимым целевой директории. Это означает, что изменения, внесенные в файлы на хосте, будут немедленно отражаться внутри контейнера, и наоборот.
Примеры использования bind mount и volume с указанием --mountв команде run:
volume: type=volume,src=my_volume,target=/usr/local/data
bind mount: type=bind,src=/path/to/data,target=/usr/local/data
Можно заметить, что volume и bind mounts отличаются только типом и значением src. В случае с volumes вы указываете название тома, а в случае с bind mounts указывается путь на хосте, который нужно опрокинуть в контейнер.
Volumes |
Bind mounts |
|
Путь на хосте |
Выбирает Docker |
Указывается разработчиком |
Создает новый volume |
Да |
Нет |
Поддерживает драйверы volumes |
Да |
Нет |
Для создания volumes и bind mount также может использоваться следующий синтаксис команды docker run: docker run -d -v /path/on/host:/path/in/container my_image в случае использования bind mounts.
Или docker volume create my_volume && docker run -d -v my_volume:/data my_image в случае использования томов.
Теперь данные по пути /data внутри контейнера будут храниться в my_volume. Volume можно отключать, заменять и делать еще много всего. Разово создав volume, пересоздавать его не нужно.
Docker Compose
Docker Compose — это мощный инструмент, разработанный для упрощения работы с многоконтейнерными приложениями. Docker Compose позволяет вам описать и запустить сложные приложения, состоящие из нескольких контейнеров, с минимальными усилиями. В этом разделе мы погрузимся в основы Docker Compose и его применение.
Основные возможности Docker Compose включают:
Декларативное описание сервисов, volumes и networks в формате yaml;
Управление всеми службами, указанными в конфигурационном файле, при помощи единой утилиты docker compose;
Управление жизненным циклом контейнеров.
Рассмотрим пример простого веб-приложения, состоящего из веб-сервера и базы данных.
Без Docker Compose запуск такого приложения потребовал бы выполнения серии команд для каждого контейнера, ручной настройки сетей и volumes. Docker Compose позволяет автоматизировать этот процесс, описав конфигурацию проекта в одном файле.
Для начала работы с Docker Compose необходимо создать файл docker-compose.yml, в котором будет описана конфигурация вашего приложения. Рассмотрим пример файла, в котором описаны два контейнера: web и db.
services:
web:
image: nginx:latest
ports:
- "8000:80"
networks:
- app-network
app:
build:
args:
user: www-data
uid: 33
app_mode: development
context: .
dockerfile: Dockerfile
restart: always
image: app
container_name: app
working_dir: /var/www/
volumes:
-'./:/var/www'
networks:
- app-network
db:
image: mysql:latest
volumes:
-'app-db:/var/lib/mysql'
environment:
DB_PASSWORD: password
networks:
- app-network
networks:
app-network:
name: app-network
driver: bridge
volumes:
app-db:
driver: local
Структура docker-compose.yml
services содержит описание всех служб (контейнеров), участвующих в работе приложения.
web: Определяет контейнер с веб-сервером Nginx, который будет доступен на порту 80.
Синтаксис "8000:80" читается так: "host_port:container_port". Докер будет слушать 8000 порт на хосте и проксировать его в nginx-контейнер и обратно.
app: главный контейнер с приложением. Описывается в Dockerfile, использует контекст текущей директории (привычная всем точка). Делает bind mount "./" в "/var/www" в контейнере.
db: Определяет контейнер с базой данных MySQL, в который передается переменная среды DB_PASSWORD. А также данные базы данных хранятся в volume app-db, чтобы не потерять информацию в случае остановки контейнера.
networks: Определяет пользовательские сети, в данном случае bridge-сеть app-network, используемую всеми контейнерами для связи друг с другом.
volumes: Определяет все необходимые тома, в данном случае том для базы данных.
Для запуска всех служб, описанных в docker-compose.yml, используйте команду: docker compose up (если у вас установлена старая версия Docker Compose, то скорее всего нужно запускать docker-compose, через дефис).
Эта команда построит, запустит и свяжет все контейнеры, описанные в файле. После выполнения команды вы будете видеть все логи в своем stdout. Добавив флаг -d, контейнеры запустятся в фоновом режиме: docker compose up -d
Чтобы остановить все контейнеры и сети, используйте команду: docker compose down
Управление контейнерами
Для управления отдельными службами Docker Compose предоставляет удобные команды.
Просмотр списка запущенных контейнеров: docker compose ps
Просмотр всех контейнеров: docker compose ps -a
Просмотр логов приложения: docker compose logs <container_name>
Перезапуск контейнера: docker compose restart <container_name>
Заключение
В этой статье мы постарались дать инструкцию по использованию базовых техник работы с Docker для тех, кто только начинает знакомство с данной технологией.
Конечно, рассказать о Docker еще можно много. Пишите, что вас интересует, и, возможно, именно ваш комментарий станет темой для нашей следующей статьи.
Комментарии (49)
riky
18.06.2024 21:14+1А что если у меня десятки мелких баз данных и я хотел бы установить один сервер mysql на хосте для использования в разных проектах. Понятно что не тру, будет работать?
vvzvlad
18.06.2024 21:14я хотел бы установить один сервер mysql на хосте для использования в разных проектах
Зачем на хосте?
riky
18.06.2024 21:14+1можно и в докере. будет сильно проще?
cat-chi
18.06.2024 21:14В общем-то всё, что нужно – чтобы до сервера mysql был доступ из проектов. И тут даже неважно, docker или не docker, важно как настроена сеть и т.п.
Может у вас все проекты в одной внутренней сети докера крутятся с mysql, тогда конечно проще.
Или у вас отдельный хост конкретно под mysql, и тогда для проектов вообще не важно, как именно он развёрнут, они с ним будут работать как с чёрным ящиком.
Тогда вопрос уже в том, важны ли накладные расходы, которые создаёт docker, на производительность диска, например.
riky
18.06.2024 21:14ну вот например есть сервис в контейнере который хочет подключиться в БД. какой хост указать в настройках сервиса чтобы он мог достучаться до mysql установленной на основном хосте? контейнеру сервиса надо добавлять сеть bridge ?
cat-chi
18.06.2024 21:14+1"Кошерный" путь – использовать особую магию докера. Добавить опцию
host.docker.internal:host-gateway
В compose-файле это будет выглядить как дополнительная запись в настройках сервиса:
extra_hosts:
- "host.docker.internal:host-gateway"После этого нужно будет настроить сервер mysql, чтобы он слушал сеть докера. И это при условии, что сервис поднят в сети докера по-умолчанию...
В общем, не знаю, шаманство какое-то, сам таким не пользовался. Проще и правда поднять mysql в контейнере в той же сети, что и сервис.
P.S. Более простой путь – выбрать тип сети host для контейнера с сервисом. Тогда он сможет дойти до mysql просто по localhost. Но это не секьюрно.
koreychenko
18.06.2024 21:14+1Можно поднять общий контейнер с базой, явно указать ему network name а дальше использовать этот network для контейнеров из других проектов, где нужно использовать эту базу.
ainu
18.06.2024 21:14+3Вообще, mysql может работать через линукс-сокеты, это надо и mysql и клиента подключить к одинаковой директории вроде
volumes:
- /var/run/mysqld/:/var/run/mysqld/
fujinon
18.06.2024 21:14Если я правильно понял, у вас на одной и той же машине БД не в контейнере и сервис в контейнере? Если так, то из внутренней сети контейнера IP-адрес хоста - это всегда 172.17.0.1.
Но как тут уже сказали, лучше БД тоже поместить в контейнер, этот контейнер добавить в сеть сервиса, и тогда у БД внутри этой сети будет hostname, совпадающий с именем сервиса БД, который указан в docker-compose.yml.mayorovp
18.06.2024 21:14IP-адрес хоста не может быть всегда 172.17.0.1 хотя бы потому, что он зависит от того, в какую сеть попал контейнер и какие у этой сети настройки.
colesnic89
18.06.2024 21:14Да хоть 50 баз данных, причем при необходимости можно даже разные версии ставить на одной хост машине
Julegg
18.06.2024 21:14+1Понятно что не тру, будет работать?
А почему не должно работать? Вам надо будет лишь в проектах задавать один и тот же адрес и указывать корректное имя базы. А в случае, если запустите в контейнере - просто следить, чтобы контейнер работал.
Вопрос только в том, что это не так уж и гибко.
InTheWeb
18.06.2024 21:14Будет, если поднять mysql как отдельный контейнер с пробросом порта на гостевую машину, все остальные контейнеры смогут взаимодействовать с ним по сети
Sly_tom_cat
18.06.2024 21:14+2Раз уж упомянут Golang и многоэтапная сборка, то неплохо бы упомянуть замечательную возможность golang - делать бинарики независимыми ни отчего вообще (ну на самом деле зависимость остается только от загрузчика программ ОС). Тогда образ второй фазы будет содержать только Go-шный бинарик.
FROM golang:1.16 AS build
WORKDIR /go/src/app
COPY . .
RUN go build -o myapp
CGO_ENABLED=0 go build -o myapp
FROM scratch
WORKDIR /root/
COPY --from=build /go/src/app/myapp .
CMD ["./myapp"]Dancho67
18.06.2024 21:14+11Эта фишка доступна любому статически компилируемому языку, не только лишь Go.
cat-chi
18.06.2024 21:14+1В других языках не всегда так просто отказаться от динамической линковки. Был болезненный опыт с C++... деталей уже не вспомню, давно было.
А в Go всё собирается статически в 99% случаев.
Кстати, а много вообще таких достаточно популярных языков, которые собирают код в статический бинарь и не тянут за собой тяжёлый рантайм?
Ну вот например, можно ли как-то наколдовать "легковесную яву" в докере? У меня в своё время не получилось, но не могу сказать, что я сильно пытался.
sergiodev
18.06.2024 21:14В чём плюс этого подхода? У вас все зависимости просто зашитиы в бинарник, и теперь их нужно перекомпилёвывать и загружать в докер каждый раз заново, в то время как одна из главных особенностей докера - отделение зависимостей в отдельные слои, чтобы их каждый раз не качать.
Я понимаю, если бы приходилось вручную деплоить экзешник на разные системы с разными установленными пакетами и потенциально без админских прав - тогда это безусловно было бы плюсом, а так не вижу преимуществ.
Sulerad
18.06.2024 21:14Если вы уже пишите на Go, то отказаться от статической линковки — задача нетривиальная. А если что так, что эдак, зависимости зашиваются в бинарник, то нет причин не уменьшить размер итогового образа.
stvoid
18.06.2024 21:14+3Вы вероятно не совсем поняли суть, которая тут происходит.
У нас имеется образ с компилятором golang (это может быть любой образ, может вы собираете ffmpeg, там огромное количество всего вам понадобится). Этот образ, условно, пусть будет весить 600мб
Компилируем бинарник (если это будет ffmpeg, то например компилируете его в один статичный бинарник, пусть на выходе это будет около 50мб)
За конечный образ берете например alpine, т.к. у вас нет никакой линковки, то бинарник будет просто запускаться. Итог: конечный готовый образ у вас будет 60мб (условно), т.е. 50мб ffmpeg + OS alpine.
Та часть dockerfile где мы компилировали мы можем выкинуть уже из системы.
Аналогично делается сборка например веб приложений - собираем фронт в образе ноды, бинарник сервера в образе чего-либо, в конечный образ копируем результаты сборки фронта и бэка в любой легкий образ.
a3000d
18.06.2024 21:14+4Адекватно неписано, хотя про базовые образы и как их создавать самому хотелось бы почитать подробнее.
cyberia_studio Автор
18.06.2024 21:14+1Спасибо! Подумаем, можем ли мы развернуть эту тему в отдельной статье.
Sagittarius67
18.06.2024 21:14+2- Создавать и делиться собственными изображениями;
Фоточки можно хранить?
MagMagals
18.06.2024 21:14может еще кто подскажет как в докере запускать ui-приложения с открытием окна этого приложения в виндувсе
Aquahawk
18.06.2024 21:14+1без докера, но запустить gui приложение на сервере и пробросить иксы на винду умеет из коробки https://mobaxterm.mobatek.net/
astroduck
18.06.2024 21:14+1К сожалению, после того как полностью прикрыли возможность использовать Docker бесплатно для бизнеса, санкции практически закрыли возможность оплачивать лицензию, а в России так и не разрешили официально пиратить буржуйское ПО, есть большие сомнения по поводу целесообразности использования Docker в серьезных проектах. А также есть опасения что и дальше будут расти лицензионные ограничения. По сути это теперь не open source, хотя они пока и заявляют обратное.
slonopotamus
18.06.2024 21:14+3использовать Docker бесплатно для бизнес
Мне кажется вы щас смешиваете три раздельные вещи:
Исходники под открытой лицензией и совершенно бесплатны
Качать образы с докерхаба можно совершенно бесплатно
Аплоадить свои образы на докерхаб... Ну я бы очень подумал хорошо ли это с т.з. безопасности.
ALexhha
18.06.2024 21:14Качать образы с докерхаба можно совершенно бесплатно
но есть лимиты
Исходники под открытой лицензией и совершенно бесплатны
ну тут скорее речь об docker desktop и иже с ними. Мы вот были вынуждены перейти на rancher desktop. Это просто боль и страдания после docker desktop
slonopotamus
18.06.2024 21:14+1но есть лимиты
Поднять у себя в контуре кэширующую прокси полезно в любом случае на случай "докерхаб упал"/"кому-нибудь в очередной раз моча в голову ударила и заблокировали сетевую связь или с той или с этой стороны".
slonopotamus
18.06.2024 21:14+1Мы вот были вынуждены перейти на rancher desktop. Это просто боль и страдания после docker desktop
А можете развернуть мысль? А то я тоже перешёл на rancher desktop и... Всё отлично работает.
И про какую операционку на хост-машине речь? А то если там линукс, то польза от всех этих *desktop очень быстро стремится к нулю.
ALexhha
18.06.2024 21:14И про какую операционку на хост-машине речь? А то если там линукс, то
польза от всех этих *desktop очень быстро стремится к нулю.macos intel/arm
А можете развернуть мысль?
когда в организации 1000+ пользователей то это боль. Начиная от ui, но это мелочи, и заканчивая непонятными вылетами. Еще была куча проблем со встроенным кубиком. И таких ошибок вагон и маленькая тележка.
последнее что нашел в слеке
% sudo launchctl load /Library/LaunchAgents/se.ivankrizsan.socat_launcher.plist Warning: Expecting a LaunchDaemons path since the command was ran as root. Got LaunchAgents instead. `launchctl bootstrap` is a recommended alternative. Load failed: 5: Input/output error Try running `launchctl bootstrap` as root for richer errors.
А то я тоже перешёл на rancher desktop и... Всё отлично работает.
у меня такая же нога и не болит ( с )
slonopotamus
18.06.2024 21:14у меня такая же нога и не болит ( с )
Очевидно что не такая же, я потому и спросил в чём разница. Из вашего ответа стало понятно, разница в том что вы используете для серверной разработки наименее подходящую для этого операционку (а уж в arm исполнении там ещё больше приколов вылезает). А зачем вы это делаете?
ALexhha
18.06.2024 21:14Из вашего ответа стало понятно, разница в том что вы используете для
серверной разработкичто за серверная разработка )))
а уж в arm исполнении там ещё больше приколов вылезает
а пацаны то и не знали, оказывается arm фуфло ))) Просветите об этом всех облачных провайдеров, а то они тоже не в курсе по ходу. Проблемы были только с ранчером, с docker desktop особых проблем не было. Отсюда делаем вывод - что дело не в ОС
наименее подходящую для этого операционку
потому что в крупных организациях MacOS это отраслевой стандарт. Всякие windows/linux идут лесом
YuriPanchul
18.06.2024 21:14В стиле статьи чувствуется запах ChatGPT.
Насколько я понимаю, главное назначение докера - это не возиться с несовместимостями между версиями питона в пакете Open Lane. Правильно?
cyberia_studio Автор
18.06.2024 21:14Главное назначение — обеспечить порядок в проектах, дать каждому приложению, развернутому в контейнере, свою, подходящую среду. Докер сам контролирует ресурсы между контерами, упрощает деплой и поддержку проектов.
Также есть вытекающие ништяки в виде упрощения ввода нового члена команды в работу на проекте и удобное управление версиями артефактов в виде образов.YuriPanchul
18.06.2024 21:14Я таких расплывчатых слов не понимаю. Что такое "порядок", "среда", "ресурсы", "образы"? Входят ли в "среду" следующее:
Существование и содержимое файла /etc/udev/rules.d/90-intel-fpga.rules
Версия tclsh, bash, prython3, make, gcc?
Установленые пакеты для питона и тикля?
Нахождение юзера в группе dialout для доступа к устройству /dev/ttyUSB0?
Что еще?
mikegordan
18.06.2024 21:14+2"Всё что нужно знать"
Мне не хватило
1) почему ничего не написано про macvlan драйвер чтобы контейнеры получали IP как виртуальные машины от роутера и были доступны по IP из любого компьютера в твоей локальной сети
2) как реализовать версионность образов. и тема как обновлять запущенные контейнеры на новые версии образов не коснулись в статье
cyberia_studio Автор
18.06.2024 21:14Версионность осуществляется с помощью тегов. Обновляется просто — обновляешь версию образа, пересоздаешь контейнер.
ALexhha
18.06.2024 21:14как реализовать версионность образов. и тема как обновлять запущенные контейнеры на новые версии образов не коснулись в статье
это уже больше про ci/cd и Docker Swarm. Докер, как таковой, к этому особого отношения не имеет
fujinon
В примере с docker compose сеть
app-network
не нужна, уберите ее совсем и docker compose создаст сеть по умолчанию.cyberia_studio Автор
Можно. Но хорошим тоном будет всегда указывать сети явно. Например, если на сервере работает не один проект, а два и больше.
mayorovp
Хорошим тоном будет не создавать лишних сетей. Сеть default создаётся всегда, и "создавая сеть явно" вы удваиваете число создаваемых сетей на проект. Зачем?
doox911
А почему удваивается?
mayorovp
Потому что 2 в 2 раза больше чем 1.
fujinon
Не совсем всегда, а когда есть хотя бы один контейнер без кастомной сети. В данном примере будет создана только одна сеть app-network, но если хотя бы в одном из 3 контейнеров закомментировать networks, то дополнительно создастся XXX_default.
mayorovp
Странно, у меня создавалась всегда...
fujinon
Просто прогоните пример из статьи и убедитесь, делов-то) только сначала придется исправить опечатки))
opusmode
Смотрите, про хороший тон я не знаю, однако объясню вам логику, которая может быть.
Итак, есть некий компоуз. В общем случае он действительно может запускаться где угодно и иметь дефолтную подсеть. Однако бывают случаи, когда мы не совсем знаем, где придётся его развернуть и толгда подсеть будет уже и не дефолтная.
Опять же, в общем случае это как бы и не проблема - ну, а какая разница? Сервисы изолированы там, порты биндятся, всё круто, так? Так, но не совсем. БЫвают случаи, когда в компоузе указываются все имеющиеся сервисы, а после создаются профили. Например сервер или кластер СУБД может быть вынесен во вне. Или быть на хосте. Или ещё как-то. Почему так? Да в целом не ажно - так бывает. А ещё там может быть фаеволл. А ещё приложение может быть составным - ну, например, разные микросервисы, которые общаются друг с другом по API. Опять же, не спрашивайте, почему такое может быть. И да, может это не совсем нормальная ситуация, но жизнь вообще не идеально.
Следовательно, мы не хотим годать, что там на хосте и в какую подсеть попадёт то или иное. Мы ведь докер зачем используем? Чтобы получать ожидаемые результаты, верно? Вот мы как бы и пишем сеть, что бы покрыть не самый удачный вариант и не гадать, каким сетян надо открыть доступы, куда стучаться, ну и вот это вот всё.
Что нам это даёт? ДА банально экономию времени, как бы отсекая потенциальный траблшутинг. Перестраховка это? Да. Надо делать нормально и лучше контролировать ситуацию? Да. Но иногда это невозможно и написание нескольких строчек впрок создаёт меньше головняка, чем 1 лишняя сеть на хосте.
А потом появляется привычка просто сразу закладывать риски, даже маловероятные.
mayorovp
Ну и какая во всех перечисленных вами случаях разница, дефолтная сеть используется контейнером или не дефолтная? Они ж отличаются только названием, и то если им название не указали явно...