【问题标题】:Bundle install and yarn install inside entry script - Docker在入口脚本中捆绑安装和纱线安装 - Docker
【发布时间】:2020-07-31 19:02:31
【问题描述】:

我看到 bundle installyarn install 通常在 Dockerfile 中完成为:

RUN bundle install && yarn install

这意味着如果我修改了 Gemfile 或 yarn.lock,我需要重新构建镜像。我知道有层缓存,docker build 不会重建除 bundle install && yarn install 层之外的其他层。但这意味着我必须这样做docker-compose up -d --build

但我想知道是否可以将这些命令放在 docker-compose 的入口脚本或命令中:

command: bundle install && yarn install && rails s

这样,我相信,每当我执行docker-compose up -dbundle installyarn install 时,无需构建映像即可执行。

除了不必在docker-compose up 中附加--build 之外,不确定它是否比Dockerfile 中的传统捆绑安装有任何优势。更正一下,如果我这样做,即使 Gemfile 或 Yarn 文件没有更改,bundle install 和 yarn install 也会执行。我想这是不好的一面。

如果这不是理想的方式,请纠正我。

Docker 世界的新手。

【问题讨论】:

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


    【解决方案1】:

    这个问题是基于意见的。正如您自己已经发现的那样,在镜像构建过程中安装依赖项(bundle、yarn、其他)是一种常见的做法,而不是镜像运行过程。

    理由是您run 的次数比您build 的次数多,并且您希望快速启动运行操作。

    与您在构建阶段执行apt install...yum install... 的方式相同,您通常也应该在构建阶段执行bundle install

    也就是说,如果将bundle install 作为入口点的一部分对您有意义,那是您的选择。我怀疑在你这样做之后,你会发现它不太常见是有原因的。

    关于 docker 层的另一个注意事项:如果 Gemfile 发生变化,不仅引用它的层会发生变化,而且所有后续层也会发生变化。因此,通常将依赖项清单 (Gemfile.*) 的副本与应用程序的副本分开,如下所示:

    # Pre-install gems
    COPY Gemfile* ./
    RUN gem install bundler && \
        bundle install --jobs=3 --retry=3 
    
    # Copy the rest of the app
    COPY . .
    

    这样,如果你的应用文件改变了,但依赖项没有改变,构建会更快。

    【讨论】:

    • “不仅引用它的层会改变,所有后续层也会改变”。那是真实的。正如我所提到的,“即使没有对 Gemfile 或 Yarn 文件进行更改,bundle install 和 yarn install 也会被执行”,这会延迟你提到的运行。感谢@DannyB 的精彩解释。
    【解决方案2】:

    每次启动应用程序时都会浪费几分钟的时间并占用网络带宽。当您进行本地开发时,就相当于这样做了,每次运行应用程序时:

    rm -rf vendor node_modules
    bundle install              # from scratch
    yarn install                # from scratch
    bundle exec rails s
    

    Docker 的一个核心部分是重建镜像(就像 Go、Java、Typescript 等语言一样。 有一个“构建”阶段)。通常不建议尝试避免图像重建。使用编写良好的 Dockerfile,特别是对于解释型语言,运行 docker build 应该是相当有效的。

    一个重要的技巧是分别复制指定依赖项的文件和应用程序的其余部分。一旦 Dockerfile COPY 指令遇到已更改的文件,它将禁用应用程序其余部分的层缓存。由于依赖关系很少更改,因此如果依赖关系文件没有更改,则首先复制依赖关系文件,然后安装依赖关系,然后复制应用程序的顺序可以直接跳到最后一步。

    COPY Gemfile Gemfile.lock ./
    RUN bundle install
    
    COPY package.json yarn.lock ./
    RUN yarn install
    
    COPY . ./
    

    (确保将 Bundler vendor 目录和 node_modules 目录包含在 .dockerignore 文件中,这样最后的 COPY 步骤不会覆盖之前安装的内容。)

    【讨论】:

    • “浪费了几分钟的时间,耗尽了网络带宽”。当然。谢谢你的解释。关于在 .dockerignore 中包含 node_modules 目录的好处。我一直在 .gitignore 中这样做,但忘记了这个。但是供应商呢。 AFAIK,它包含 3rd 方库,不应该将它们也复制到 docker 映像吗?
    • bundle install 将为您安装它们;出于与node_modules 目录相同的原因,您希望将它们从 Docker 构建上下文中排除。
    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多