如何使用Elastic Beanstalk和Dockerrun.aws.json正确地部署到AWS?

4

我目前拥有一个本地工作并且在hub.docker.com上私有托管的docker镜像。

容器内部我有rails、puma和nginx。Elastic Beanstalk能够成功从docker hub拉取镜像,但之后无法执行任何操作。

AWS有nginx,并返回给我这个错误。有人能指出我哪里做错了吗?

AWS错误日志

-------------------------------------
/var/log/nginx/error.log
-------------------------------------
2014/12/27 08:48:34 [emerg] 3161#0: no host in upstream ":80" in           /etc/nginx/conf.d/elasticbeanstalk-nginx-docker-upstream.conf:2

更多 AWS 错误日志

nginx: [emerg] no host in upstream ":80" in /etc/nginx/conf.d/elasticbeanstalk-nginx-    docker-upstream.conf:2
nginx: configuration file /etc/nginx/nginx.conf test failed
Failed to start nginx, abort deployment (Executor::NonZeroExitStatus)
    at /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/executor-1.0/lib/executor/exec.rb:81:in `sh'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/executor-1.0/lib/executor.rb:15:in `sh'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/executable.rb:63:in `execute!'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/hook-directory-executor.rb:29:in `block (2 levels) in run!'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/activity.rb:169:in `call'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/activity.rb:169:in `exec'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/activity.rb:126:in `timeout_exec'
    from /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.1.0/gems/beanstalk-core-1.0/lib/elasticbeanstalk/activity.rb:110:in `block

错误的源文件
upstream docker {
        server :80;
        keepalive 256;
}

这里是我拥有的文件。
Dockerfile
FROM ruby:2.1.5

#################################
# native libs
#################################

RUN apt-get update -qq
RUN apt-get install -qq -y build-essential
RUN apt-get install -qq -y libpq-dev
RUN apt-get install -qq -y nodejs
RUN apt-get install -qq -y npm
RUN apt-get install -qq -y nginx

# Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

#################################
# Install Nginx.
#################################

RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN chown -R www-data:www-data /var/lib/nginx
ADD config/nginx.conf /etc/nginx/sites-enabled/default

EXPOSE 80

#################################
# Symlinking Nodejs for ubuntu
#   -- https://dev59.com/I18d5IYBdhLWcg3w41nz
#################################
RUN ln -s /usr/bin/nodejs /usr/bin/node

#################################
# NPM install globals
#################################

RUN npm install bower -g

#################################
# Rails
#################################

RUN mkdir /app
WORKDIR /app
ADD . /app

ENV RAILS_ENV production
ENV SECRET_KEY_BASE test123

RUN bundle install --without development test
RUN bundle exec rake bower:install
RUN bundle exec rake assets:precompile

CMD foreman start -f Procfile

Dockerrun.aws.json

{
  "AWSEBDockerrunVersion": "1",
  "Authentication": {
    "Bucket": "aws-bucket",
    "Key": ".dockercfg"
  },
  "Image": {
    "Name": "ericraio/my-image",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "80"
    }
  ],
  "Logging": "/var/log/nginx"
}

NGINX

upstream rails_app {
  server unix:///app/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  # listen 80 deferred;
  # server_name domain.tld www.domain.tld;
  root /app/public;

  try_files $uri/index.html $uri @rails_app;

  location @rails_app {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://rails_app;
  }

  error_page 500 504 /500.html;
  error_page 502 /502.html;
  error_page 503 /503.html;

  client_max_body_size 4G;
  keepalive_timeout 10;
}
2个回答

7
问题在于,在EC2上容器无法运行。亚马逊使用该命令来构建IP地址并设置一个环境变量。
EB_CONFIG_NGINX_UPSTREAM_IP=$(docker inspect `cat $EB_CONFIG_DOCKER_STAGING_APP_FILE` | jq -r .[0].NetworkSettings.IPAddress)

然后亚马逊使用此行来构建IP地址。
EB_CONFIG_NGINX_UPSTREAM_PORT=`cat $EB_CONFIG_DOCKER_STAGING_PORT_FILE`

我将端口80暴露出来,但由于我的容器无法运行,因此我没有主机。这就是为什么你会看到这个错误。

在上游中找不到主机“:80”


但是为什么容器会失败呢?我正在 Docker 中部署一个 Java 应用程序,在 :9000 上出现了相同的错误。 - Chris Fellows
2
@ChrisFellows 如果您的容器无法运行,那么亚马逊将无法构建IP地址。亚马逊确实需要输出错误消息。尝试在本地构建和运行容器以查看输出内容。 - ericraio
本地运行良好没问题。同时,执行 docker ps -a 命令可以看到 Docker 容器正在运行。但是如果我尝试 curl 127.0.0.1:9000(这是 Dockerfile 中 EXPOSE 的端口),它会失败。无法连接。仍在努力查找根本原因。 - Chris Fellows
终于搞定了。尽管文档说Dockerfile会优先于Dockerrun.aws.conf,但是Dockerrun中的某些东西搞乱了一切。我只是把它移除了,然后一切都正常工作了。我不知道那里面到底出了什么问题。这是我整理的一个博客文章,里面包含一些关键的日志和配置文件。希望能对其他人有所帮助。 - Chris Fellows
@ChrisFellows 非常棒! - ericraio

1

如上所述,容器可能已经失败。部署脚本无法找到NGINX必须转发调用的IP地址。

因此,这个异常不是最初的原因。为了知道最初发生了什么:

  1. 使用SSH连接到您的EC2实例
  2. sudo docker ps -a
  3. 确定与您的应用程序相关联的容器ID(该命令是查找它的好方法)。
  4. sudo docker logs [CONTAINER ID]

我在这个页面上找到了答案:https://forums.aws.amazon.com/thread.jspa?messageID=626464


谢谢!在我的情况下,容器拒绝优雅地关闭,因此启动新容器的部署命令由于缺乏内存而失败。重新启动解决了这个问题(暂时)。 - Jonathan Richards

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接