使用位于另一个docker容器中的nginx提供静态文件

时间:2017-07-18 14:14:32

标签: nginx docker static

刚开始,我看到了this。但他/她使用build,我使用image

我有一个docker-compose文件,它将我之前制作的图像拉到我的服务器上。

app:
  restart: always
  image: some-app-image:latest

nginx config

location /static/ {
    root /data/app/web_interface;  <--- this exists in some-app-image container
}

通常情况下,我会将一个卷安装到包含静态文件的应用程序映像上。

然而,由于app容器本身具有静态文件,因此这变得多余。

所有nginx容器需要做的是“对等”进入应用程序容器并提供这些静态文件。像:

location /static/ {
    root http://app:8000/web_interface;
}

location /static/ {
    root app/web_interface;
}

有没有办法从nginx容器中提供位于另一个容器中的静态文件?

4 个答案:

答案 0 :(得分:2)

我过去的所有想法:

将docker卷从app共享到nginx

您可以在应用的Dockefile中创建一个卷,并在容器运行时复制静态文件。然后使用volumes_from与nginx容器共享卷。如果您的应用depends_on nginx,这有点难看,根本不起作用。我会说这是绝对禁止,因为它在扩展您的应用容器时效果非常好。

将静态文件从主机映射到nginx容器的想法也不是最佳的。你将有一个额外的奇怪步骤来处理它们。

分隔静态容器

构建另一个nginx容器,仅为其他虚拟主机上的静态文件提供服务。 static.foo.bar

使用CDN

有大量的CDN可以放置你的静态文件,大多数框架都有插件来处理它。我有一些项目正在这样做。效果很好。

使用uWSGI

您可以使用--static-map使用uWSGI提供静态文件。见docs。这就是我最终要做的事情,因为这是一个便宜又简单的...而且在扩展方面很友好。然后你可能还需要使用http-socket,所以uWSGI会改为http。

答案 1 :(得分:1)

这是一个很晚的答案,但是请添加它以防其他人找到。

也许您可以利用服务器缓存,以便NGINX在对应用程序进行首次请求后可以有效地从其文件系统提供静态文件。

Here is a good guide to caching with NGINX

由于资产是静态的,您可以将无效标志设置为较长时间。


基于上述指南的基本示例:

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=30d use_temp_path=off;

server {
  ...

  location /static {
    proxy_cache my_cache;
    proxy_pass http://app:8000/static; # <--- wherever static files are on app server
  }

  ...
}

答案 2 :(得分:1)

我做了类似但不同的事情

我让docker-compose运行两个容器:nginx和flaskapp。我让Nginx容器处理静态请求,并将其余请求转发到flask应用程序。这是我的Nginx配置(flaskapp.conf):

class User_Add_PickUp_Form extends Component {
  constructor(props) {
    super(props);
    this.state = {
      owner: this.props.loginUser,
      lines: '',
      stations: '',
      textInput: '',
      allLines: '',
      allStations: '',
    };
    this.handleChange = this.handleChange.bind(this);
  }

  spreadAndSetState = (key, value) => {
    this.setState({ ...this.state, [key]:value });
  };

  componentDidMount() {
    console.log('Original is ' + this.state.lines)
    axios
      .get('http://express.heartrails.com/api/json?method=getLines&prefecture=TOKYO')
      .then((res) => {
        console.log(res.data)
        this.setState({ allLines: res.data.response.line })
      })
      .catch((err) => console.log(err));
  }

  componentDidUpdate(prevState){
    console.log(prevState)
    console.log(this.state)
    if(prevState.lines != this.state.lines){
      axios.get('http://express.heartrails.com/api/json?method=getStations&line=' + this.state.lines)
      .then((res)=> {
        //
        // res.data.response.stations is going to be an array
        // 
        res.data.response.station.map((station) => {
        this.spreadAndSetState(this.state.allStations, station.name)
        })
      })
    }
  }

  handleChange = (e) => {
    const name = e.target.name;
    const value = e.target.value;

    this.spreadAndSetState(name,value)
  };

  render() {
    const { owner, lines, stations, textInput, allLines, allStations } = this.state;
    if (allLines === '') {
      return <CircularProgress />;
    } else {
      return (
        <div>
          <h2>Add Pickup Places</h2>
          <select name="lines" onChange={this.handleChange}>
            <option value="">Choose a line</option>
            {allLines.map((line) => {
              return <option value={line}>{line}</option>;
            })}
          </select>
          <select name="lines" onChange={this.handleChange}>
            <option value="">Choose a station</option>
            {allLines.map((line) => {
              return <option value={line}>{line}</option>;
            })}
          </select>
        </div>
      );
    }
  }
}

和我的nginx容器的dockerfile:

server {
listen 80;
server_name $SERVER_NAME;

location ^~ /static/  {
    include  /etc/nginx/mime.types;
    root /;
}

location / {
    proxy_set_header Host $host;
    proxy_pass http://frontend:8000;
}
}

我复制了一个拥有所需资产的静态文件夹,现在可以将其加载到前端。

答案 3 :(得分:0)

解决方案之一是在app服务开始时将资产复制到共享卷:

docker-stack.yml

volumes:
  docroot:
services:
  site:
    volumes:
      - docroot:/docroot
  nginx:
    volumes:
      - docroot:/docroot

app服务的entrypoint.sh

#!/usr/bin/env sh
rsync -a --delete --exclude /uploads public/ /docroot
# start the site

WORKDIR位于/app。位于/app/public的docroot。在这里,我还使其不复制uploads目录。

here上的更多内容。