在 Elasticbeanstalk Docker 环境中提供 Django 静态文件

Posted

技术标签:

【中文标题】在 Elasticbeanstalk Docker 环境中提供 Django 静态文件【英文标题】:Serving Django static files in Elasticbeanstalk Docker environment 【发布时间】:2018-10-11 07:50:06 【问题描述】:

使用 docker 环境将 Django 应用程序部署到 EB 时,静态文件返回 404。

我在 docker 容器上使用 gunicorn,由于不推荐/不可能(?)通过 gunicorn 提供静态文件,我想配置 EB nginx 以使用主机文件系统为它们提供服务。

Dockerfile

FROM python:3
....
....
# Expose listen ports
EXPOSE 8002

RUN chmod +x ./docker/container_start.sh

CMD ["sh", "./docker/container_start.sh"]

Dockerrun.aws.json


  "AWSEBDockerrunVersion": "1",
  "Ports": [
    
      "ContainerPort": "8002"
    
  ],
  "Volumes": [
    
      "ContainerDirectory": "/app/assets",
      "HostDirectory": "/var/app/current/assets"
    
  ]

我如何告诉 EB nginx 从 /var/app/current/assets 提供 /assets/* 并将其余部分代理到 docker 容器?

由于 docker 环境,下面的内容不起作用。

option_settings:
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "www/static/"

【问题讨论】:

您找到解决方案了吗? 【参考方案1】:

总结一下我们在使用SolutionStackName: 64bit Amazon Linux 2 v3.2.0 running Docker 的 elasticbeanstalk docker 容器中运行的 django 提供静态文件的解决方案:

    在容器真正准备就绪之前,我们不想运行collectstatic。为此,我们在 entrypoint.sh 中启动它,不久之后它也会启动 gunicorn。 我们让collectstatic 将静态文件从我们的设置中拖放到“static”中:
STATIC_ROOT = "static"
STATIC_URL = "/static/"
    我们在.platform/hooks/postdeploy 中配置一个部署后脚本,将静态文件从容器中复制到/var/app/current 中的ec2 vm(脚本运行的地方):
#! /bin/bash
docker cp $(docker ps --no-trunc -q | head -n 1):/home/app/static .
    我们通过在.platform/nginx/conf.d/elasticbeanstalk/custom.conf 中放置自定义配置文件来告诉 nginx 在哪里可以找到静态文件:
location /static/ 
    root /var/app/current/;

就是这样。它对我们有用。

【讨论】:

只需要更改/home/app/static 否则就像一个魅力【参考方案2】:

我也遇到了同样的问题!解决方案是在服务器上的 /etc/sites-enabled/elasticbeanstalk-nginx-docker-proxy.conf 中自定义 nginx 配置。

基本上,我将该文件的内容复制到 .ebextension 配置文件中,并为静态文件夹添加了 location 指令。

所以你的 Dockerrun.aws.json


  "AWSEBDockerrunVersion": "1",
  "Ports": [
    
      "ContainerPort": "8002"
    
  ],
  "Volumes": [
    
      "ContainerDirectory": "/app/assets",
      "HostDirectory": "/var/app/current/assets"
    
  ]

您将创建 .ebextension/01_nginx.config

files:
  "/etc/nginx/sites-enabled/elasticbeanstalk-nginx-docker-proxy.conf":
  mode: 000644
  owner: root
  group: root
  content: |
    map $http_upgrade $connection_upgrade 
        default        "upgrade";
        ""            "";
    

    server 
        listen 80;

        gzip on;
        gzip_comp_level 4;
        gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        if ($time_iso8601 ~ "^(\d4)-(\d2)-(\d2)T(\d2)") 
            set $year $1;
            set $month $2;
            set $day $3;
            set $hour $4;
        
        access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;

        access_log    /var/log/nginx/access.log;

        location /assets/ 
          root /var/app/current;
        

        location / 
            proxy_pass            http://docker;
            proxy_http_version    1.1;

            proxy_set_header    Connection          $connection_upgrade;
            proxy_set_header    Upgrade             $http_upgrade;
            proxy_set_header    Host                $host;
            proxy_set_header    X-Real-IP           $remote_addr;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        
    

这对我有用!

【讨论】:

这个答案不对! 当宿主卷被挂载时,它会挂载到容器中指定目录的内容之上。然后该目录的内容将不可用于主机。看到这个问题:***.com/questions/42848279/… 嗯......你知道它对我有用,这不仅仅是我说的。你试过了吗? 是的,我自己尝试过,当它不起作用时需要重新设计一些东西。您确定系统的行为方式与您描述的方式相同吗?例如,我在您的 EB Dockerrun 配置中看到主机上的静态目录是 /var/app/current/assets,但在您的 nginx 配置中,静态目录是 /var/current 也许您在 docker 中运行的 webapp 实际上是在为静态资产提供服务? 你是对的。这是一个错误,我已将实际路径更改为通用路径,显然是错误的。应该是/var/app/current/。我会马上修改编辑【参考方案3】:

你想做的事情是不可能的。

您不能将/host-dir 挂载到/container-dir 上并期望主机读取挂载前存在的/container-dir 的内容。 (/container-dir 的内容是隐藏的。)见this question/answer。

您可能希望将静态资产包含在 Elastic Beanstalk 捆绑包中,而不是包含在 docker 映像中。如果您这样做,这些资产将出现在 /var/app/current 中,然后您可以告诉 Elastic Beanstalk 的内置 nginx 将它们用作 per the other answer in this thread。

【讨论】:

可以使用现有容器内容填充卷:docs.docker.com/storage/volumes/… 如果您启动一个创建新卷的容器,如上所述,并且容器在目录中有文件或目录要挂载(如上面的/app/),目录的内容被复制到卷中。 @SuneKjærgård 在您链接到的文档中,它解释说容器将使用目录的内容填充 新卷 - 然后可以在其他 容器。但是,它不会替换您已作为“共享”挂载到容器上的主机上的目录的内容。 @SuneKjærgård 这是我的终端的输出,我试图明确地证明我的观点:gist.github.com/topher515/e56430e7e0c12c2aa8b5aa30eb24bc97

以上是关于在 Elasticbeanstalk Docker 环境中提供 Django 静态文件的主要内容,如果未能解决你的问题,请参考以下文章

无法将多容器 docker 部署到 ElasticBeanstalk

Docker 容器在本地工作,但在上传到 elasticbeanstalk 时不工作

如何在 Elasticbeanstalk 环境中运行的 docker 容器中承担 AWS 角色?

ElasticBeanstalk - 无法从私有 Docker Hub 存储库中提取 docker 映像

502 Bad Gateway nginx/1.14.1 elasticbeanstalk .net core app 在 docker 上运行

在 Elasticbeanstalk Docker 环境中提供 Django 静态文件