# dockek
## Что?



### что такое, зачем нужно
- аналог -- виртуальная машина (но докер-контейнеры легче и удобнее в использовани)и
- система контейнеризации приложений, позволяет облегчить развертывание, благодаря тому, что необходимые сервисы "упаковываются" внутрь контейнера вместе с зависимостями
- использует [unionFS](https://habr.com/ru/company/skillfactory/blog/547116/) (не то чтобы нужно знать, но иногда полезно это учитывать при написании докерфайлов)
- кроссплатформенный
- работает как `client - daemon`. У вас поднимается докер-демон, который менеджит локальные контейнеры, в случае чего пуллит недостающие (например). взаимодействе с ним осуществляется через клиента (`docker` в консольке, например)
### установка
- вообще [тут](https://www.docker.com/)
- но! должен быть доступен в вашем пакетном менеджере (про brew не уверен)
## getting started
### container
[тут!](https://docs.docker.com/engine/reference/run/)
- к этому можно относиться как к мини-виртуалке с любым линуксом под капотом на ваш скромный вкус
***потыкаем***:
так, например, можно заспавнить себе убунту:
```
❯ docker run -t -d --name ubunta ubuntu
274f4ee47ac8694939d156c5c6de1fba5fc8f80cd65656477f56d51c746cdb60
```
- `-t` -- заспавнить tty. Примечательно, что если в контейнере нет работающих процессов -- он умирает
- `-d` -- запустить контейнер в бекграунде
- `--name` -- ну вы поняли
- `ubuntu` -- имя образа
а вот так можно развернуть постгрес за 0 секунд:
```
❯ docker run --name postgreskek -e POSTGRES_PASSWORD=mysecretpassword -d postgres
6e676f8c862f4cb202062518fa5cabe4a2f439971a2ca3247bd5e831e4302a5c
❯ docker ps # так можно посмотреть список запущенных контейнеров
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e676f8c862f postgres "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 5432/tcp postgreskek
274f4ee47ac8 ubuntu "bash" 20 minutes ago Up 20 minutes ubunta
816667d6b6a4 ubuntu "bash" 50 minutes ago Up 50 minutes kek
```
- `-e` -- прокидывает в контейнер указанные переменные окружения
- отметим, что постгресс внутри контейнера разворачивается на каком-то порту, который затем пробрасывается на `5432` порт локальной сети (или не локальной). При желании порты можно прокидывать еще, например, так:
-- `-p 127.0.0.1:8080:80/tcp` (здесь 8080 -- порт в контейнере, 80 -- порт который доступен снаружи)
*или так*
-- `-p 8080:80`
*или так*
-- `--expose 80`
**а еще существуют вольюмы!**

-- это общие директории, которые делят наша файловая система и фс контейнера (указанная директория банально маунтится внутрь)
```
❯ docker run --name vo -d -t -v /home/whiskey/vol:/vol ubuntu
```
- первый аргумент -- откуда, второй -- куда
***ну и всякое***
- с контейнерами можно делать еще всякие-разные вещи, вот самое банальное и частоиспользуемое
```
exec docker exec -it <name> <cmd> # запускает ваши команды внутри контейнера
restart docker restart <name>
rm docker rm <name>
kill docker kill <name>
ps/list docker ps # список всех запущенных контейнеров (вообще всех - с флагом "--all")
```
### image
- "read-only" шаблон для создания контейнера. Зачастую вы не хотите с нуля собирать контейнер (например, когда пишете докерфайл), так как логично взять за основу что-то существующее. Если вы хотите написать что-то на джанге (питон-фреймворк), в таком случае можно использовать образ с установленным питоном, например.
```
FROM python:3.7-alpine <--- образ
COPY marks /marks
COPY requirements.txt requirements.txt
```
***cписок всех образов:***
```
❯ docker image list # список всех образов
REPOSITORY TAG IMAGE ID CREATED SIZE
wodby/drupal 9-4.40.3 07b70fa30175 12 days ago 484MB
wodby/mariadb 10.7-3.17.1 1a7eb68ce620 2 weeks ago 283MB
wodby/nginx 1.21-5.21.3 35c6896f8513 2 weeks ago 38.8MB
server_bot latest 6e8ebba19963 9 months ago 1.45GB
exoplanet_exoplanet latest 02ad170d9f2d 10 months ago 910MB
mysql 5.7 87eca374c0ed 11 months ago 447MB
mailhog/mailhog latest 4de68494cd0d 19 months ago 392MB
traefik v2.0 2874b2a534b9 2 years ago 69.3MB
drupal 8.0.0 0312ffeb007b 6 years ago 571MB
```
***Главное помнить, что спулленные образы занимают место на диске (иногда очень много), поэтому имеет смысл чистить их раз в какое-то время:***
```
❯ docker system prune # удалить неиспользуемые образы
❯ docker system prune -a # удалить вообще все
```
***Существуют специальные хранилища образов, как глобальные ([докерхаб](https://hub.docker.com/)), так и [локальные](https://docs.docker.com/registry/)***
### dockerfile
* Файл c инструкциями, по которым будет собираться ваш контейнер (или образ)
* каждая строчка докерфайла -- новый слой (см. про unionFS)
***коротко про основной синтаксис:***
```
FROM python:3.7-alpine
COPY marks /marks
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
WORKDIR /marks
RUN touch db.sqlite3
RUN python3 manage.py makemigrations && python3 manage.py migrate
EXPOSE 8000
CMD ["gunicorn", "-b", "0.0.0.0:8000", "--workers=2", "--threads=4", "marks.wsgi"]
```
- `FROM ...` -- здесь указывается родительский образ
- `COPY <from> <to>` -- копирует файлы/директории в контейнер. Первый аргумент -- откуда (с вашего компухтера), второй -- куда (внутрь контейнера)
- `WORKDIR <dir>` -- устанавливает директорию, относительно которой будут выполняться последующие команды
- `EXPOSE <port>` -- открывает порт внтури контейнера
- `CMD ["arg1", "arg2", ...]` - аргументы, с которыми будет запускаться контейнер. их можно переопределять в командной строке.
`docker run --name test test/test-backend /srv/www/bin/gunicorn.sh <-- переопределение CMD`
в докерфайле `CMD` может присутствовать лишь один раз.
*также еще бывают:*
- `ENV <var>=value` -- делает переменную окружения
- `ADD <from> <to>` -- тоже самое, что и `COPY`, только умнее. Умеет, например, брать файл по ссылке. Но вообще не рекомендуется к использованию.
- `ENTRYPOINT ["arg1", "arg2", ...]` -- похоже на `CMD`, однако не переопределяется
ну и еще много [других](https://docs.docker.com/engine/reference/builder/)
***С помощью докерфайлов можно создавать образы:***
```
❯ docker build <dockerfile_path>
```
***Но что делать, если мы захотим одновременно управлять >1 докер-контейнером?***
### docker-compose !!
- docker-compose используется для одновременного управления несколькими контейнерами, входящими в состав приложения. он предлагает те же возможности, что и докер, но позволяет работать с более сложными приложениями.
***выглядит это как-то так***:
```
# docker-compose.yaml
version: '3.0' # версия
services: # список сервисов, в будущем - образов иконтейнеров
marks: # название сервиса
build: # Опции для того, чтобы сбилдить образ
context: . # директория, содержащая докерфайл, или путь до гит-репозитория с ним
dockerfile: docker_config/backend/Dockerfile # сам докерфайл, из которого будет билдится образ
restart: on-failure # опция для рестарта контейнера
ports: # порты!
- 10010:8000
bot:
build:
context: .
dockerfile: docker_config/bot/Dockerfile
restart: on-failure
redis: # редис, в данном случае, не требует докерфайла, его можно билдить просто по образу. Стоит заметить, что наличие секции image не исключает секцию build.
image: redis:5.0.5-alpine
restart: on-failure
```
***запускатеся так***
```
❯ docker-compose up --build -d
```
- Появились образы. Почему их больше чем 3? дело в том, что на каждый из двух докерфайлов в docker-compose приходится еще по одному образу, от корого он наследуется.
```
❯ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
server_bot latest 88f300fc75b5 15 seconds ago 1.57GB
server_marks latest 17325b8078c5 About a minute ago 92.9MB
python 3.7-alpine c36f68524a0e 8 days ago 46.3MB
python 3.7 b5b74728b4f4 8 days ago 903MB
redis 5.0.5-alpine ed7d2ff5a623 2 years ago 29.3MB
```
- А вот активные контейнеры:
```
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95d803b318d7 server_marks "gunicorn -b 0.0.0.0…" 2 minutes ago Up 2 minutes 0.0.0.0:10010->8000/tcp, :::10010->8000/tcp server-marks-1
31fce1d91e7c server_bot "python3 bot.py" 2 minutes ago Up 2 minutes server-bot-1
11cf77ab8d84 redis:5.0.5-alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 6379/tcp server-redis-1
```
***выключается так***
```
❯ docker-compose down
```
- флаг `--build` будет ребилдить сервисы каждый раз, если он указан. Запуск приложения без этой опции приведет к продолжению работы (как до выключения (`down`))
***Также еще существуют команды:***
```
docker-compose logs
docker-compose restart
...
```
и [другие](https://docs.docker.com/compose/)
их суть, кажется, понятна, или, по крайней мере, достаточно описана
### кажется, это все..
