【问题标题】:Confusion while deploying docker-composer image部署 docker-composer 映像时的困惑
【发布时间】:2016-12-25 20:17:48
【问题描述】:

我一直在使用示例 ruby​​-on-rails 应用程序并在 linux 服务器 (ubuntu 14.04) 中部署 docker 映像。

这是我的 Dockerfile:

FROM ruby:2.1.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /rails_docker_demo
WORKDIR /rails_docker_demo
ADD Gemfile /rails_docker_demo/Gemfile
ADD Gemfile.lock /rails_docker_demo/Gemfile.lock
RUN bundle install
ADD . /rails_docker_demo

# CMD bundle exec rails s -p 3000 -b 0.0.0.0
# EXPOSE 3000

docker-compose.yml:

version: '2'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    image: atulkhanduri/rails_docker_demos
    volumes:
      - .:/rails_docker_demo
    ports:
      - "3000:3000"
    depends_on:
      - db

部署.sh:

#!/bin/bash

docker build -t atulkhanduri/rails_docker_demo .
docker push atulkhanduri/rails_docker_demo

ssh username@ip-address << EOF
docker pull atulkhanduri/rails_docker_demo:latest
docker stop web || true
docker rm web || true
docker rmi atulkhanduri/rails_docker_demo:current || true
docker tag atulkhanduri/rails_docker_demo:latest atulkhanduri/rails_docker_demo:current
docker run -d --restart always --name web -p 3000:3000 atulkhanduri/rails_docker_demo:current
EOF

现在我的问题是我无法使用docker-compose 之类的命令来运行应用程序服务器,例如docker-compose up

当我取消注释来自Dockerfile 的最后两行时,即

CMD bundle exec rails s -p 3000 -b 0.0.0.0    
EXPOSE 3000

然后我可以在端口3000 上运行服务器,但出现错误could not translate host name "db" to address: Name or service not known。 (我的 database.yml 有“db”作为主机。)这是因为 postgres 图像未被使用,因为我没有使用 docker-compose 文件。

编辑:

docker network ls的输出:

NETWORK ID          NAME                DRIVER              SCOPE
b466c9f566a4        bridge              bridge              local               
7cce2e53ee5b        host                host                local               
bfa28a6fe173        none                null                local

P.S:我在互联网上搜索了很多,但还不能使用docker-compose 文件。

【问题讨论】:

    标签: ruby-on-rails docker docker-compose dockerfile


    【解决方案1】:

    假设

    如果我正确地阅读了您在此处所做的事情,我的回答假定以下两件事。

    1. 您正在使用 docker-compose 运行数据库容器。

    2. 您正在使用普通的 docker 命令(不是 docker-compose)来启动应用程序服务器(“web”)。

    首先,我建议不要这样做,对两者都使用 docker-compose 要简单得多。但是,我会根据上面的内容来回答,假设有一些正当的理由你不能使用 docker-compose 来运行“web”容器。

    关于容器和网络名称

    当您运行 docker-compose 命令启动 db 容器时,除其他外,会发生两件事。

    1. 容器被赋予了一个新名称,由运行 compose 设置的目录、compose 中的静态名称 (db) 和一个数字组成。因此,假设您将所有这些都放在一个名为 myapp 的目录中,您将拥有一个名为 myapp_db_1 的新容器。您可以使用docker ps 查看它的名称。

    2. 如果网桥不存在,则会创建一个网桥,命名为 myapp_default - 再次,以撰写设置所在的目录命名。

    连接到正确的网络

    问题是您的非撰写容器连接到默认网络(可能是docker_default),但您的数据库容器连接到myapp_default。这两个网络彼此不了解。你需要连接它们。告诉 Web 应用容器附加到 compose 网络可能更有意义。

    首先,获取正确的网络名称。您可以使用docker network ls 查看所有网络。它可能看起来像这样:

    $ docker network ls
    NETWORK ID          NAME                       DRIVER              SCOPE
    c1f5764a112b        bridge                     bridge              local
    175efb89adef        docker_default             bridge              local
    5185ff0e1054        myapp_default              bridge              local
    

    获得正确名称后,使用--network 选项更新运行命令以了解网络。

    docker run -d --restart always --name web \
        -p 3000:3000 --network myapp_default \
        atulkhanduri/rails_docker_demo:current
    

    一旦连接到正确的网络,名称“db”应该会正确解析。

    如果您使用 docker-compose 来启动它们,则没有必要(这是 docker-compose 默默为您处理的事情之一)。

    让它在你的服务器上运行

    在 cmets 中,您提到您在服务器上遇到了一些撰写问题。你具体说:

    我需要在服务器上复制我的完整项目吗?我不能只从 docker 映像运行应用程序吗?实际上,我在服务器中复制了docker-compose,它为Gemfile 抛出了错误,然后我复制了Gemfile,然后它说它应该是一个rails 应用程序。所以我想我需要在服务器中复制我的完整文件夹。你能确认一下吗?

    让我们看一下 Dockerfile 的某些部分。我将添加一些内联的 cmets。

    ## Make a new directory, and then make it the current directory
    RUN mkdir /rails_docker_demo
    WORKDIR /rails_docker_demo
    
    ## Copy Gemfile and Gemfile.lock into this directory from outside
    ADD Gemfile /rails_docker_demo/Gemfile
    ADD Gemfile.lock /rails_docker_demo/Gemfile.lock
    
    ## Run the bundle installer, which will install to this directory
    RUN bundle install
    
    ## Finally, copy everything from the outside local dir to here
    ADD . /rails_docker_demo
    

    所以,很明显,/rails_docker_demo 是您在容器中的应用程序目录。你在这里安装了一堆东西,这将成为你的形象的一部分。当您将映像推送到注册表,然后将其拉到服务器上时(就像在部署脚本中所做的那样),这一切都会随之而来。

    现在让我们看看(一些)docker-compose.yml。

    services:
      web:
        volumes:
          - .:/rails_docker_demo
    

    在这里,您定义了一个卷挂载,将当前目录(docker-compose.yml 所在的位置)挂载为/rails_docker_demo。当你这样做时,服务器上发生的任何事情现在都可以在/rails_docker_demo 中使用,但是这个挂载取消了我刚才提到的 Dockerfile 中的所有工作。您没有在构建映像时安装的资源,而是只有服务器上 . 目录中的所有资源。挂载位于映像的现有 /rails_docker_demo 目录之上,隐藏其内容并用当前服务器上的任何内容替换它们。

    除非你把这个挂载放在这里是有原因的,否则你可能只需要从 docker-compose.yml 中删除那个卷挂载。您仍然需要服务器上的 docker-compose.yml,但您不应该需要它的其余部分(当然,除了图像)。

    您所做的这个挂载是一件有用的事情 - 用于开发目的。它可以让您使用容器来运行应用程序并快速显示代码更改(无需重建映像)。但就您的部署而言,它只会造成麻烦。

    【讨论】:

    • 我尝试在deploy.sh 中使用docker-compose (docker-compose up) 命令,替换docker run 命令。但它会引发错误Can't find a suitable configuration file in this directory or any parent. 如果您向我提供使用docker-compose 运行网络应用程序的命令,将会很有帮助。
    • 我的docker network ls 也显示NETWORK ID NAME DRIVER SCOPE b466c9f566a4 bridge bridge local 7cce2e53ee5b host host local bfa28a6fe173 none null local 我已经更新了这个问题。
    • @AtulKhanduri 您是否正在将 docker-compose.yml 复制到服务器?我看到你在哪里构建图像,推送到注册表。我看到你 ssh 到服务器,拉取图像并启动它,但如果 docker-compose.yml 在服务器端不可用,那么 docker-compose 将不可用。这是您的错误所暗示的:(“在此目录或任何父目录中找不到合适的配置文件。”)
    • 我需要在服务器上复制我的完整项目吗?我不能只从 docker 映像运行应用程序吗?实际上,我在服务器中复制了docker-compose,它为Gemfile 抛出了错误,然后我复制了Gemfile,然后它说它应该是一个rails 应用程序。所以我想我需要在服务器中复制我的完整文件夹。你能确认一下吗?
    • @AtulKhanduri 这可能是由于您的卷安装。我已经编辑了我的答案以添加关于该问题的部分。
    【解决方案2】:

    尝试将EXPOSE 移到CMD 上方,例如

    FROM ruby:2.1.5
    RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
    RUN mkdir /rails_docker_demo
    WORKDIR /rails_docker_demo
    ADD Gemfile /rails_docker_demo/Gemfile
    ADD Gemfile.lock /rails_docker_demo/Gemfile.lock
    RUN bundle install
    ADD . /rails_docker_demo
    
    EXPOSE 3000
    CMD bundle exec rails s -p 3000 -b 0.0.0.0
    

    【讨论】:

    • 我不确定它是否会工作,因为我可以使用docker 而不是docker-compose 运行应用程序服务器,因此db 容器位于不同的网络中应用服务器,正如 Dan Lowe 的回答所建议的那样。不过,我会试试你的解决方案。
    猜你喜欢
    • 2018-11-12
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多