【问题标题】:Different result using docker-compose vs docker run使用 docker-compose 与 docker run 的不同结果
【发布时间】:2017-05-27 20:07:42
【问题描述】:

我正在建立一个通用的公共数据库,我可以与其他容器链接到该数据库。我在使用docker-composedocker 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 在尝试登录时也会给我“拒绝访问”。

谁能告诉我为什么在使用 docker-compose 但不能使用 docker 时数据卷正确安装并且 phpmyadmin 能够通信?

【问题讨论】:

  • 可能只是您映射卷的方式有误。在 docker-compose 文件中使用 "./data:.." ,在 docker run 命令中使用 "data:.." 。所以它取决于你运行 docker run 命令的位置/你的 docker-compose.yml 文件所在的位置。对于 docker-compose.yml,所有路径都相对于文件所在的位置。
  • 两个命令都在同一个目录中执行。当我尝试在 docker 命令中使用 ./data 时,它给我一个错误,即路径由于前导点而无效。

标签: docker phpmyadmin docker-compose mariadb


【解决方案1】:

docker-compose 和你的 docker run 行都对我有用。请注意,您不需要 -P 标志,文档说这会将所有公开的端口发布到随机端口——这可能不是您想要的,因为您还指定了 -p 标志。

 -P, --publish-all                 Publish all exposed ports to random ports

【讨论】:

    【解决方案2】:

    使用以下命令:

    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 \
    

    干杯!

    【讨论】:

      【解决方案3】:

      正如其他人所指出的,不同之处在于您指定卷路径的方式。但到目前为止,没有人解释为什么,即使您在 docker run 中“错误地”指定了卷,Docker 却毫无错误地接受了它们并继续运行,或者为什么您看到了您所看到的行为。

      码头工人撰写

      在 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
      

      很明显,您的意思是“使用相对路径”。正如您已经提到的,如果您在此处指定带有前导 ./ 的相对路径,您将收到错误,即您不能这样做:

      -v ./conf:/etc/mysql/conf.d -v ./data:/var/lib/mysql -v ./logs:/var/log/mysql
      

      发生了什么

      您注意到,当您通过 docker-compose 运行时,它会按预期工作:使用主机安装的卷。但是当您通过docker run 运行时,数据将保存在容器内,并且不使用主机挂载的目录。为什么?

      原因是您使用的-v 语法确实 有一个有效的目的,只是不是您想的那样。按照您指定的方式,您创建了 named Docker 卷。冒号前的前导部分遵循以下规则:

      1. 如果看到前导./,这是一个相对目录:错误
      2. 如果看到前导/,这是一个绝对路径。将卷挂载到容器中。
      3. 如果您提供类似foo/bar 的内容,则假定这是一个相对路径。 错误
      4. 最后,如果您指定word:/some/path,那么word 将被视为一个名称。一个名为 word 的 Docker 卷被创建,并安装在容器中的 /some/path

      所以当使用docker run 时,您创建了卷。这些在容器内使用。卷正在使用中,只是没有安装在主机上的卷。

      无法连接错误

      我认为您的网络设置没有任何问题。我对您的连接错误的最佳猜测是,在docker run 场景中,您的数据库没有正确设置,因此 phpmyadmin 无法使用 mysql。如果您更正了音量问题并且 phpmyadmin 仍然存在问题,请使用您遇到的任何特定错误更新您的问题,并对我的答案发表评论,以便我再次查看。

      参考

      Docker run reference (VOLUME)

      -v, --volume=[host-src:]container-dest[:]:绑定挂载一个卷。
      逗号分隔的选项是 [rw|ro], [z|Z],
      [[r]shared|[r]slave|[r]private] 和 [nocopy]。
      'host-src' 是绝对路径或名称值。

      名称值必须以字母数字字符开头,后跟 a-z0-9、_(下划线)、. (句点)或 - (连字符)。绝对路径以 /(正斜杠)开头。

      Manage data in containers (Removing volumes)

      删除容器后,Docker 数据卷仍然存在。您可以创建命名或匿名卷。命名卷在容器外具有特定的源形式,例如awesome:/bar。匿名卷没有特定来源。

      【讨论】:

        最近更新 更多