Это часть типичного docker-compose.yml, который часто встречается в интернете
services:
mariadb:
image: 'mariadb:latest'
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE=redmine
volumes:
- './mariadb_data:/var/lib/mysql'
[...]Просто и безопасно, верно? Экземпляр MariaDB без root-пароля, работающий в отдельном контейнере и не имеющий открытого порта 3306 — поэтому только сервисы из того же docker-compose.yml могут получить к нему доступ, поскольку docker-compose помещает все эти сервисы в отдельную сеть.
Неверно.
Хотя экземпляр MariaDB недоступен из интернета, к нему может обратиться любой процесс через его внутренний IP-адрес.
Чтобы понять, что происходит, рассмотрим сети docker. В этом случае моя конфигурация docker-compose называется redmine.
$ docker network ls | grep redmine
ea7ed38f469b redmine_default bridge localЭто сеть, которую docker-compose создаёт без явной конфигурации сети. Давайте inspect сеть, чтобы показать хосты:
[
// [...]
"Containers": {
"2578fc65b4dab9f204d0a252e421dd4ddd9f41c35642d48350f4e59370581757": {
"Name": "redmine_mariadb_1",
"EndpointID": "1e6d81acc096a12fc740173f4e107090333c42e8a86680ac5c9886c148d578e7",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"7867f71d2a36265c34c133b70aea487b90ea68fcf30ecb42d6e7e9a376cf8e07": {
"Name": "redmine_redmine_1",
"EndpointID": "f5ac7b3325aa9bde12f0c625c4881f9a6fc9957da4965767563ec9a3b76c19c3",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
// [...]
]Мы видим, что IP-адрес контейнера redmine_mariadb_1 — 172.18.0.2.
Используя внутренний IP 172.18.0.2, вы можете получить доступ к серверу MySQL.
Любой процесс на хосте (даже от непривилегированных пользователей) может подключиться к контейнеру без пароля, например
$ mysqldump -uroot -h172.18.0.2 --all-databases
// This will show the dump of the entire MariaDB databaseКак устранить этот риск для безопасности?
Устранение довольно простое, поскольку нам нужно только установить root-пароль для экземпляра MariaDB.
Моя рекомендуемая лучшая практика — избегать дублирования паролей. Для этого создайте файл .env в директории, где находится docker-compose.yml.
MARIADB_ROOT_PASSWORD=aiPaipei6ookaemue4voo0NooC0AeHНе забудьте заменить пароль на случайный или используйте этот скрипт для автоматического создания:
echo MARIADB_ROOT_PASSWORD=$(pwgen 30) > .envТеперь мы можем использовать ${MARIADB_ROOT_PASSWORD} в docker-compose.yml везде, где требуется root-пароль MariaDB, например:
services:
mariadb:
image: 'mariadb:latest'
environment:
- MYSQL_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
- MYSQL_DATABASE=redmine
volumes:
- './mariadb_data:/var/lib/mysql'
redmine:
image: 'redmine:latest'
environment:
- REDMINE_USERNAME=admin
- REDMINE_PASSWORD=redmineadmin
- REDMINE_EMAIL=ukoehler@techoverflow.net
- REDMINE_DB_MYSQL=mariadb
- REDMINE_DB_USERNAME=root
- REDMINE_DB_PASSWORD=${MARIADB_ROOT_PASSWORD}
ports:
- '3718:3000'
volumes:
- './redmine_data/conf:/usr/src/redmine/conf'
- './redmine_data/files:/usr/src/redmine/files'
- './redmine_themes:/usr/src/redmine/public/themes'
depends_on:
- mariadb