使用 docker-compose 与 docker 运行 的不同结果
Different result using docker-compose vs docker run
我正在设置一个通用的公共数据库,我可以 link 与其他容器连接。使用 docker-compose
和 docker run
.
时我遇到了不同的结果
docker-compose.yml
mysql:
image: mariadb:10.1
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root-secret
MYSQL_USER: dbuser
MYSQL_PASSWORD: my-secret
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
pma:
image: phpmyadmin/phpmyadmin
links:
- mysql:db
ports:
- 8088:80
environment:
MYSQL_ROOT_PASSWORD: root-secret
MYSQL_USER: dbuser
MYSQL_PASSWORD: my-secret
我运行的docker命令是:
docker run -d -P --name mysql -v conf:/etc/mysql/conf.d -v data:/var/lib/mysql \
-v logs:/var/log/mysql -e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser -e MYSQL_PASSWORD=my-secret -p 3306:3306 mariadb:10.1
docker run -d --name pma --link mysql:db -e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser -e MYSQL_PASSWORD=my-secret -p 8088:80 phpmyadmin/phpmyadmin
使用 docker-compose up -d
时,一切正常,我主机的数据目录中充满了数据库文件。此外,phpmyadmin 能够毫无问题地连接到数据库容器。
当使用 docker 命令时,主机的数据目录保持为空,数据存储在容器中。 phpmyadmin 在尝试登录时也给了我 "access denied"。
谁能告诉我为什么数据量正确挂载并且 phpmyadmin 在使用 docker-compose 而不是 docker 时能够通信?
docker-compose 和您的 docker 运行 行对我都有效。请注意,您不需要 -P
标志,文档说这会将所有公开的端口发布到随机端口 - 可能不是您想要的,因为您还指定了 -p
标志。
-P, --publish-all Publish all exposed ports to random ports
使用以下命令:
docker run -d -P --name mysql \
-v $(pwd)/conf:/etc/mysql/conf.d \
-v $(pwd)/data:/var/lib/mysql \
-v $(pwd)/logs:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser \
-e MYSQL_PASSWORD=my-secret \
-p 3306:3306 \
mariadb:10.1
docker run -d --name pma \
--link mysql:db \
-e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser \
-e MYSQL_PASSWORD=my-secret \
-p 8088:80 \
phpmyadmin/phpmyadmin
原因
您没有正确安装卷。在 docker-compose.yml
文件中,您要指定相对于文件所在目录的路径
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
然而,在 docker run
命令中,您没有使用相对路径
-v conf:/etc/mysql/conf.d -v data:/var/lib/mysql -v logs:/var/log/mysql
此外,docker run
要求您指定要挂载到容器内的本地目录的绝对路径。
因此,您必须使用类似于 docker-compose.yml
的语法来获取绝对路径,或者手动编写您的路径。
-v /path/to/conf:/etc/mysql/conf.d \
-v /path/to/data:/var/lib/mysql \
-v path/to/logs:/var/log/mysql \
干杯!
正如其他人所指出的,区别在于指定卷路径的方式。但是到目前为止,没有人解释为什么即使您在 docker run
中指定了卷 "incorrectly",Docker 也没有错误地接受了它们并继续前进,或者为什么您看到了您所看到的行为。
docker-compose
在 docker-compose.yml 中,你使用了这个:
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
在这种情况下,您将采用本地相对路径,前导 ./
,并使用绝对路径安装在容器内。这很好用。
docker 运行
在您的 docker run
命令中,您使用了这个:
-v conf:/etc/mysql/conf.d -v data:/var/lib/mysql -v logs:/var/log/mysql
很明显,您的意思是 "use the relative path." 正如您已经提到的,如果您在此处指定带有前导 ./
的相对路径,则会出现错误,即您不能这样做:
-v ./conf:/etc/mysql/conf.d -v ./data:/var/lib/mysql -v ./logs:/var/log/mysql
发生了什么事
您注意到,当您通过 docker-compose 运行 时,它按您预期的方式工作:使用主机安装的卷。但是,当您通过 docker run
运行 时,数据将保留在容器内,并且不会使用主机安装的目录。为什么?
原因是您使用的 -v
语法 确实 有一个有效的目的,只是不是您所想的那样。按照您指定的方式,您创建了 named Docker 卷。冒号前的前导部分遵循以下规则:
- 如果看到前导
./
,则这是一个相对目录:错误
- 如果看到前导
/
,则这是绝对路径。将卷装入容器。
- 如果您给出类似
foo/bar
的内容,则假定这是一个相对路径。 错误
- 最后,如果您指定
word:/some/path
,则 word
将被视为名称。 Docker 卷已创建,名称为 word
,并安装在位于 /some/path
的容器中。
因此,当使用 docker run
时,您创建了卷。这些在容器内使用。卷正在使用中,只是没有 host-mounted 卷。
无法连接错误
我认为您的网络设置没有问题。我对您的连接错误的最佳猜测是在 docker run
场景中,您的数据库设置不正确,因此 phpmyadmin 无法使用 mysql。如果您更正了音量问题并且 phpmyadmin 仍然存在问题,请使用您遇到的任何特定错误更新您的问题,并对我的回答发表评论以便我再次查看。
参考资料
-v, --volume=[host-src:]container-dest[:]: Bind mount a volume.
The comma-delimited options are [rw|ro], [z|Z],
[[r]shared|[r]slave|[r]private], and [nocopy].
The 'host-src' is an absolute path or a name value.
A name value must start with an alphanumeric character, followed by a-z0-9, _ (underscore), . (period) or - (hyphen). An absolute path starts with a / (forward slash).
Manage data in containers (Removing volumes)
A Docker data volume persists after a container is deleted. You can create named or anonymous volumes. Named volumes have a specific source form outside the container, for example awesome:/bar
. Anonymous volumes have no specific source.
我正在设置一个通用的公共数据库,我可以 link 与其他容器连接。使用 docker-compose
和 docker run
.
docker-compose.yml
mysql:
image: mariadb:10.1
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root-secret
MYSQL_USER: dbuser
MYSQL_PASSWORD: my-secret
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
pma:
image: phpmyadmin/phpmyadmin
links:
- mysql:db
ports:
- 8088:80
environment:
MYSQL_ROOT_PASSWORD: root-secret
MYSQL_USER: dbuser
MYSQL_PASSWORD: my-secret
我运行的docker命令是:
docker run -d -P --name mysql -v conf:/etc/mysql/conf.d -v data:/var/lib/mysql \
-v logs:/var/log/mysql -e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser -e MYSQL_PASSWORD=my-secret -p 3306:3306 mariadb:10.1
docker run -d --name pma --link mysql:db -e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser -e MYSQL_PASSWORD=my-secret -p 8088:80 phpmyadmin/phpmyadmin
使用 docker-compose up -d
时,一切正常,我主机的数据目录中充满了数据库文件。此外,phpmyadmin 能够毫无问题地连接到数据库容器。
当使用 docker 命令时,主机的数据目录保持为空,数据存储在容器中。 phpmyadmin 在尝试登录时也给了我 "access denied"。
谁能告诉我为什么数据量正确挂载并且 phpmyadmin 在使用 docker-compose 而不是 docker 时能够通信?
docker-compose 和您的 docker 运行 行对我都有效。请注意,您不需要 -P
标志,文档说这会将所有公开的端口发布到随机端口 - 可能不是您想要的,因为您还指定了 -p
标志。
-P, --publish-all Publish all exposed ports to random ports
使用以下命令:
docker run -d -P --name mysql \
-v $(pwd)/conf:/etc/mysql/conf.d \
-v $(pwd)/data:/var/lib/mysql \
-v $(pwd)/logs:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser \
-e MYSQL_PASSWORD=my-secret \
-p 3306:3306 \
mariadb:10.1
docker run -d --name pma \
--link mysql:db \
-e MYSQL_ROOT_PASSWORD=root-secret \
-e MYSQL_USER=dbuser \
-e MYSQL_PASSWORD=my-secret \
-p 8088:80 \
phpmyadmin/phpmyadmin
原因
您没有正确安装卷。在 docker-compose.yml
文件中,您要指定相对于文件所在目录的路径
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
然而,在 docker run
命令中,您没有使用相对路径
-v conf:/etc/mysql/conf.d -v data:/var/lib/mysql -v logs:/var/log/mysql
此外,docker run
要求您指定要挂载到容器内的本地目录的绝对路径。
因此,您必须使用类似于 docker-compose.yml
的语法来获取绝对路径,或者手动编写您的路径。
-v /path/to/conf:/etc/mysql/conf.d \
-v /path/to/data:/var/lib/mysql \
-v path/to/logs:/var/log/mysql \
干杯!
正如其他人所指出的,区别在于指定卷路径的方式。但是到目前为止,没有人解释为什么即使您在 docker run
中指定了卷 "incorrectly",Docker 也没有错误地接受了它们并继续前进,或者为什么您看到了您所看到的行为。
docker-compose
在 docker-compose.yml 中,你使用了这个:
volumes:
- ./conf:/etc/mysql/conf.d
- ./data:/var/lib/mysql
- ./logs:/var/log/mysql
在这种情况下,您将采用本地相对路径,前导 ./
,并使用绝对路径安装在容器内。这很好用。
docker 运行
在您的 docker run
命令中,您使用了这个:
-v conf:/etc/mysql/conf.d -v data:/var/lib/mysql -v logs:/var/log/mysql
很明显,您的意思是 "use the relative path." 正如您已经提到的,如果您在此处指定带有前导 ./
的相对路径,则会出现错误,即您不能这样做:
-v ./conf:/etc/mysql/conf.d -v ./data:/var/lib/mysql -v ./logs:/var/log/mysql
发生了什么事
您注意到,当您通过 docker-compose 运行 时,它按您预期的方式工作:使用主机安装的卷。但是,当您通过 docker run
运行 时,数据将保留在容器内,并且不会使用主机安装的目录。为什么?
原因是您使用的 -v
语法 确实 有一个有效的目的,只是不是您所想的那样。按照您指定的方式,您创建了 named Docker 卷。冒号前的前导部分遵循以下规则:
- 如果看到前导
./
,则这是一个相对目录:错误 - 如果看到前导
/
,则这是绝对路径。将卷装入容器。 - 如果您给出类似
foo/bar
的内容,则假定这是一个相对路径。 错误 - 最后,如果您指定
word:/some/path
,则word
将被视为名称。 Docker 卷已创建,名称为word
,并安装在位于/some/path
的容器中。
因此,当使用 docker run
时,您创建了卷。这些在容器内使用。卷正在使用中,只是没有 host-mounted 卷。
无法连接错误
我认为您的网络设置没有问题。我对您的连接错误的最佳猜测是在 docker run
场景中,您的数据库设置不正确,因此 phpmyadmin 无法使用 mysql。如果您更正了音量问题并且 phpmyadmin 仍然存在问题,请使用您遇到的任何特定错误更新您的问题,并对我的回答发表评论以便我再次查看。
参考资料
-v, --volume=[host-src:]container-dest[:]: Bind mount a volume.
The comma-delimited options are [rw|ro], [z|Z],
[[r]shared|[r]slave|[r]private], and [nocopy].
The 'host-src' is an absolute path or a name value.A name value must start with an alphanumeric character, followed by a-z0-9, _ (underscore), . (period) or - (hyphen). An absolute path starts with a / (forward slash).
Manage data in containers (Removing volumes)
A Docker data volume persists after a container is deleted. You can create named or anonymous volumes. Named volumes have a specific source form outside the container, for example
awesome:/bar
. Anonymous volumes have no specific source.