Info and Registry

docker info - Информация обо всём в установленном Docker
docker history - История образа
docker tag - Дать тег образу локально или в registry
docker login - Залогиниться в registry
docker search - Поиск образа в registry
docker pull - Загрузить образ из Registry себе на хост
docker push - Отправить локальный образ в registry

Container Management

docker ps -а - Посмотреть все контейнеры
docker start container-name - Запустить контейнер
docker kill/stop container-name - Убить (SIGKILL) /Остановить (SIGTERM) контейнер
docker logs --tail 100 container-name - Вывести логи контейнера, последние 100 строк
docker inspect container-name - Вся инфа о контейнере + IP
docker rm container-name - Удалить контейнер (поле каждой сборки Dockerfile)
docker rm -f $(docker ps -aq) - Удалить все запущенные и остановленные контейнеры
docker events container-name
docker port container-name - Показать публичный порт контейнера
docker top container-name - Отобразить процессы в контейнере
docker stats container-name - Статистика использования ресурсов в контейнере
docker diff container-name - Изменения в ФС контейнера

Images

docker build -t my_app . - Билд контейнера в текущей папке, Скачивает все слои для запуска образа
docker images / docker image ls
- Показать все образы в системе
docker image rm / docker rmi image - Удалить image
docker commit  <containerName/ID> lepkov/debian11slim:version3- Создает образ из контейнера
docker insert URL - вставляет файл из URL в контейнер
docker save - Сохранить образ в .tar в STDOUT с тегами, версиями, слоями
docker load - Загрузить образ в .tar в STDIN с тегами, версиями, слоями
docker import - Создать образ из .tar
docker image history --no-trunc - Посмотреть историю слоёв образа
docker system prune -f - Удалит все, кроме используемого (лучше не использовать на проде, ещё кстати из-за старого кеша может собираться cтарая версия контейнера)

Run

docker run -d -p 80:80 -p 22:22 debian:11.1-slim sleep infinity (--rm удалит после закрытия контейнера) - Запуск контейнера интерактивно или как демона/detached (-d), Порты: слева хостовая система, справа в контейнере, пробрасывается сразу 2 порта 80 и 22, используется легкий образ Debian 11 и команда бесконечный сон

docker exec -it container-name /bin/bash (ash для alpine) - Интерактивно подключиться к контейнеру для управления, exit чтобы выйти
docker attach container-name - Подключиться к контейнеру чтоб мониторить ошибки логи в реалтайме

Volumes

docker cp file <containerID>:/ - Скопировать в корень контейнера file
docker cp <containerID>:/file . - Скопировать file из корня контейнера в текущую директорию командной строки
docker volume create todo-db - Создать volume для постоянного хранения файлов
docker run -dp 3000:3000 --name=dev -v todo-db:/etc/todos container-name - Добавить named volumу todo-db к контейнеру (они ok когда мы не заморачиваемся где конкретно хранить данные)
docker run -dp 3000:3000 --name=dev --mount source=todo-db,target=/etc/todos container-name - тоже самое что команда сверху
docker volume ls - Отобразить список всех volume’ов
docker volume inspect - Инспекция volume’ов
docker volume rm - Удалить volume

Network

docker network create todo-app - Создать сеть
docker network rm - Удалить сеть
docker network ls - Отразить все сеть
docker network inspect - Вся информация о сети
docker network connect - Соединиться с сетью
docker network disconnect - Отсоединиться от сети

Пробросить текущую папку в контейнер и работать на хосте, -w working dir, sh shell

docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
node:12-alpine \
sh -c "yarn install && yarn run dev"

Запуск контейнера с присоединением к сети и заведение переменных окружения

docker run -d \
--network todo-app --network-alias mysql \ (алиас потом сможет резолвить докер для других контейнеров)
-v todo-mysql-data:/var/lib/mysql \ (автоматом создает named volume)
-e MYSQL_ROOT_PASSWORD=secret \ (в проде нельзя использовать, небезопасно)
-e MYSQL_DATABASE=todos \ (в проде юзают файлы внутри конейнера с логинами паролями)
mysql:5.7

Запуск контейнера с приложением

docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"

Variables


.env файл это только для Docker Compose
ARG используются только во время билда в Dockerfile, контейнеры не имеют доступа к ним, но значения ARG можно присвоить в ENV переменные в Dockerfile
ENV переменные доступны и в билде и в контейнере

Пример Dockerfile со всеми переменными / variables

# Build with this command: docker build -t envvars_image:latest .
# Run with this: docker run -d -e "VAR4=I'm from start command" --env-file=env_file --name envvars_container envvars_image:latest
# Connect with this: docker exec -it envvars_container /bin/ash
FROM alpine:latest
#VAR1 with no default value will end up with an error if no --build-arg VAR1="I'm from ARG" provided
ARG VAR1="I'm from ARG" #or VAR1 "I'm from ARG"
ENV VAR2=$VAR1
ENV VAR3="I'm env variable"
CMD ["sleep","infinity"]

#example: docker run -e VAR5 alpine env (pass value from host)
#example: docker run --env-file=env_file alpine env (contents:VAR6="I'm from env_file")
#Use printenv to look for environment variables inside the container
#Use docker inspect to look for environment variables

Файл env_file, содержимое:
VAR5=I'm from env_file

CMD VS ENTRYPOINT

Разница в том, что CMD выполняется из под /bin/sh по дефолту, а ENTRYPOINT без него.
В случае с CMD, команда и параметры к ней захардкожены в образ, пример запуска с переопределением команды CMD ["sleep","10"]

docker run ubuntu sleep 5

Контейнер проспит 5 секунд вместо 10.

В случае с ENTRYPOINT, только команда захардкожена в образ, пример запуска с переопределением команды ENTRYPOINT ["sleep"] CMD ["10"] (Есл используются обе директивы, то в энтрипоинте команда, а в cmd параметры к ней)

docker run ubuntu 5

Контейнер проспит 5 секунд вместо 10.
Чтобы переопределить ENTRYPOINT:

docker run --entrypoint another-command ubuntu 20

Обычно практика такая, всегда используй CMD, если только не требуется каждый раз запускать контейнер с разным параметром (экономия времени, чтоб каждый раз не вводить строчку с командой)

Best Practice

Следуй принципу минимальных привилегий, процессы в контейнере никогда не должны выполняться из под рута, кроме редких случаев, нужно добавлять команду user и менять юзера на non-root.
Не привязываться к UID, он динамичен, можно записать во временную папку UID.
Сделать все исполняемые файлы владельцем рута, чтобы никто не изменил исполняемые файлы, а пользователю достаточно только права на выполнение.
Чем меньше компонентов и открытых портов, тем меньше поверхность для атак.
Использовать multistage для промежуточного контейнера для компиляции всего, зависимостей, временных файлов, образ может весить на треть меньше.
Distroless с чистого листа, использовать минимальный набор пакетов, например избавиться от образа Ubuntuи выбрать Debian-base, наши контейнеры содержат уязвимости изначального образа, чекать это.
Нужно обновлять всё до того, как выйдет из под поддержки.
Оставлять только те порты, которые реально нужны, избегать 22 и 21 3389 (ssh & ftp & rdp).
Никогда не помещайте логины/пароли в команде, в докерфайлах, переменных, docker secret или любой другой менеджер секретов ok.
Не использовать ADD, только COPY (когда используем точку - это воркдир где лежит докерфайл).
При сборке используйте .dockerignore чтобы убрать сенситив дату, это как .gitignore.
При сборке вначале команд лучше кешировать команду ран, а потом скопировать исходные данные.
Метадату записать.
Использовать тесты типа Linter и сканеры образов для CI.
Время от времени делать prune, докер любит много места жрать

Поделиться