【问题标题】:Docker - executing mkdir, chown & chgrp after the container is upDocker - 在容器启动后执行 mkdir、chown 和 chgrp
【发布时间】:2017-09-05 16:01:19
【问题描述】:

我正在尝试使用 docker-compose 创建一个 docker 容器,它在本地文件系统上安装一个卷(对于容器的 /var/www/html),然后添加一个名为 maps 和 chowns 的目录,chmods 是 www -data,以便网络服务器可以将文件写入其中。

我尝试了几种方法,使用如下 entrypoint.sh 脚本:

Dockerfile

FROM php:5.6-apache
COPY apache-config.conf /etc/apache2/sites-enabled/000-default.conf
RUN a2enmod rewrite headers
RUN service apache2 restart
COPY entrypoint.sh /entrypoint.sh
RUN chmod 0755 /entrypoint.sh

docker-compose.yml({} 中的内容仅来自 .env 文件)

version: '2'

services:
  webserver:
    build: ./docker/webserver
    image: web
    ports:
      - "8080:80"
    volumes:
      - ./web:${APACHE_DOC_ROOT}
    links:
      - db
    environment:
      - HTTP_ROOT=http://${DOCKER_HOST_IP}:${DOCKER_HOST_PORT}/
      - PHP_TMP_DIR=${PHP_TMP_DIR}
      - APACHE_LOG_DIR=${APACHE_LOG_DIR}
      - APACHE_DOC_ROOT=${APACHE_DOC_ROOT}/
      - SERVER_ADMIN_EMAIL=${SERVER_ADMIN_EMAIL}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}

入口点.sh

#!/bin/sh

mkdir /var/www/html/maps
chown www-data /var/www/html/maps
chgrp www-data /var/www/html/maps
exec "$@"

我也尝试过不使用任何 entrypoint.sh 内容,只需将其添加到 composer.yml(在环境键之后):

    command: bash -c "mkdir /var/www/html/maps && chown www-data /var/www/html/maps && chgrp www-data /var/www/html/maps"

但是这两种方法似乎在 docker-compose 日志中都没有错误,除了

webserver_1 以代码 0 退出

【问题讨论】:

    标签: docker docker-compose


    【解决方案1】:

    不确定您是否仍然遇到此问题,但添加此问题可能会对您有所帮助。我的意思是,它解决了我的问题 - 在容器上运行的 PHP 脚本没有写入权限。

    RUN usermod -u 1000 www-data
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      对于 docker 和 WordPress 安装插件、模板或创建文件夹的权限问题,您可以在 Dockerfile 中使用带有 chown 参数的命令 COPY。如下:

      COPY [--chown=<user>:<group>] <src>... <dest>
      

      例如,在我运行 wordpress 的代码中,我使用:

      COPY --chown=www-data:www-data ./app/ /var/www/html/ 
      

      但是你需要有最新版本的 Docker 才能使用 chown 参数。很多人得到未知的 chown 参数,这是由于 Docker 版本而发生的。所以在使用 chown 之前,我表示要更新你的 Docker。

      关于 COPY 命令的 Docker 参考:https://docs.docker.com/engine/reference/builder/#copy

      关于权限和 www-data 用户的 Wordpress 参考:https://codex.wordpress.org/Changing_File_Permissions

      【讨论】:

        【解决方案3】:

        正如@Fortis 和@whites11 指出的那样,我正在覆盖original PHP 5.6 Dockerfile 中现有的CMD。 Dockerfile reference - Understand how CMD and ENTRYPOINT interact 中描述了 CMD 和 ENTRYPOINT 的各种组合 - 我相信我在矩阵的右下角,将原始 Dockerfile 中的“CMD exec_cmd”(在本例中为“CMD apache-foreground”)与 ENTRYPOINT [“exec_entry”,“p1_entry”]。

        所以,在我的 Dockerfile 中,我只需要运行在原始 Dockerfile 中设置的 apache-foreground 脚本,如下所示:

        ENTRYPOINT ["/entrypoint.sh", "apache2-foreground"]
        

        并让 entrypoint.sh 以:

        结尾
        exec "$@"
        

        这允许我做我需要做的事情(在我的 docker-compose.yml 中创建一个挂载到本地文件系统的卷,然后使用 entrypoint.sh 创建和 chown + chmod 一个本地用户在该挂载内的目录& 从容器内部分组),然后按照原始 Dockerfile 的意图执行 /apache2-foreground。

        我最初在 entrypoint.sh 中测试了运行 apache2-foreground,它也可以工作,但我认为这是一种不太“透明”的方法,我想更好的解耦,以便让原作者Dockerfile 来更改他们的 Dockerfile 中的 CMD 并且我的设置不会因此而中断,我应该将他们的 CMD 传递到我的 Dockerfile ENTRYPOINT 定义中,有点像......

        ENTRYPOINT ["/entrypoint.sh", CMD]
        

        但我不知道这是否可能?

        【讨论】:

          【解决方案4】:

          php docker 镜像本身有它自己的command 条目和entrypoint,如您所见in its Dockerfile,您正在覆盖它们。因此,它不是按应有的方式运行apache2-foreground,而是运行您的自定义命令和入口点,从而创建目录、更改权限和退出。请注意,容器必须有一个长时间运行的进程才能保持正常运行。

          相反,您可以将以下命令添加到 Dockerfile(尚未运行,可能会出现错误):

          RUN mkdir -p /var/www/html/ && chown www-data /var/www/html/maps && chgrp www-data /var/www/html/maps
          

          或者如果您不关心在单个层中运行它们,您可以将它们分解为单独的 RUN 语句。

          您还应该删除以下行:

          COPY entrypoint.sh /entrypoint.sh
          RUN chmod 0755 /entrypoint.sh
          

          然后再次运行docker-compose build webserver

          【讨论】:

          • 感谢@Fortis,您在原始Dockerfile 中覆盖CMD 是对的,我没有发现这一点-但是不使用您建议的入口点脚本的问题是,当我随后挂载代码时从容器中 /var/www/html 的本地文件系统中,我们已经从 /var/www/html 中的 Dockerfile 所做的更改被覆盖。在您的帮助下,我使用入口点脚本找到了答案 - 请查看我的答案并让我知道您的想法...
          【解决方案5】:

          php:5.6-apache 镜像已经定义了入口点。

          如果您使用自定义脚本覆盖它,则需要调用原始入口点才能使图像正常工作。

          检查here,你会看到原来的入口点是

          ENTRYPOINT ["docker-php-entrypoint"]
          

          您可以尝试从您的脚本中执行它,例如:

          #!/bin/sh
          
          mkdir /var/www/html/maps
          chown www-data /var/www/html/maps
          chgrp www-data /var/www/html/maps
          docker-php-entrypoint "$@"
          

          这是未经测试的,但应该可以工作。

          【讨论】:

          • 谢谢@whites11 - 关于我重写 CMD 是对的,我不明白这一点 - 但是当我实施你的建议时,在运行 endpoint.sh 并创建了目录等时,网络服务器从不网络服务器容器仍然无法出现 - docker-compose 日志给出:“gastrakweb_webserver_1 exited with code 0” - 但你的回答帮助我弄清楚了我认为 - 请查看/评论我的答案......
          【解决方案6】:

          您可以在自己的 docker 文件中添加这些命令(COPY、CHMOD)。

          # Copy FileDirectory public html pages
            COPY FileDirectory/var/www/html /var/www/html
            RUN chmod +x /var/www/html
          

          看看我的 docker 文件https://github.com/RohanMohite/Docker-Nginx-PHP/blob/master/server1/Dockerfile

          如果您需要更多信息来设置 Dockerize PHP 应用程序,请查看https://devopsdevelopment.wordpress.com/2017/08/02/how-to-configure-docker-with-nginx-and-php-application/

          请告诉我。

          【讨论】:

          • 谢谢,除了我不想复制也不想 chmod。根据我想从 docker-compose 挂载本地卷的问题(例如,在您希望对这些文件具有本地编辑能力的开发环境中),然后在其中创建并 chown/chmod 一个目录,以便 Web 服务器有能力写进去。
          猜你喜欢
          • 1970-01-01
          • 2021-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-16
          • 2020-07-17
          • 2018-09-29
          相关资源
          最近更新 更多