构建Docker容器时,最佳实践是构建小型容器映像。较小的Docker映像往往具有更快的构建时间和拉取时间。此外,使用小型Docker映像也有安全优势-与大型Docker容器相比,小型容器的受攻击面较小。

Rails docker容器应该有多小?每个应用程序都是不同的。我的经验法则是将容器大小保持为300MB(压缩后为100MB)。功能齐全的 Rails应用程序docker映像很容易具有大约1GB的大小!这是一个例子:

 rails new myapp -d postgresql -m https://raw.githubusercontent.com/excid3/jumpstart/master/template.rb

将基本的Dockerfile与ruby: 2.5.1基本映像一起使用:

FROM ruby:2.5.1
RUN apt-get update \
    && apt-get install -y apt-transport-https \
    && curl --silent --show-error --location \
      https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key 
      add - \
    && echo "deb https://deb.nodesource.com/node_6.x/ stretch main" 
      > /etc/apt/sources.list.d/nodesource.list \
    && curl --silent --show-error --location 
      https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" > 
      /etc/apt/sources.list.d/yarn.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
    postgresql-client nodejs apt-transport-https yarn \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /usr/src/app
ENV RAILS_ENV=production
ENV NODE_ENV=production
COPY Gemfile* package.json yarn.lock ./
RUN bundle install
RUN yarn install
COPY . .
RUN bin/rails assets:precompile
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

我们最终得到一个大小为1.48GB 的docker镜像:

REPOSITORY            TAG    SIZE   
small-docker-images    v1    1.48GB

那么如何控制Docker映像大小呢?

1.使用较小的基本镜像

在第一个版本中v1,我们使用ruby:2.5.1非常方便但又很大的基本镜像。

REPOSITORY            TAG    SIZE 
ruby                  2.5.1  869MB

从较小的基本镜像开始可以减小最终镜像的大小。较小的基本镜像的示例是ruby-alpine

REPOSITORY          TAG           SIZE 
ruby                2.5.1-alpine  45.3MB

删除了大约820MB!

使用Alpine映像作为基本镜像可能会涉及更多,您必须运行一些命令并安装更多软件包:

FROM ruby:2.5.1-alpine
RUN apk update \
&& apk upgrade \
&& apk add --update --no-cache \
build-base curl-dev git postgresql-dev \
yaml-dev zlib-dev nodejs yarn
WORKDIR /usr/src/app
ENV RAILS_ENV=production
ENV NODE_ENV=production
COPY Gemfile* package.json yarn.lock ./
RUN bundle install
RUN yarn install
COPY . .
RUN bin/rails assets:precompile
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

使用alpine镜像后,我们最终得到一个小的最终v2图像,约占一半v1

REPOSITORY            TAG   SIZE
small-docker-images   v2   810MB

但是我们可以进一步减少它!

2.通过多步骤docker构建减少层数

正如git repo的大小随提交/更改次数的增加而增加一样,最终docker映像的大小也取决于层数。您可以通过减少RUNCOPY语句的数量或执行类似于“ git squash”的多步骤构建来减少层数。

这是我使用多步骤构建方法的新Dockerfile:

FROM ruby:2.5.1-alpine AS build-env
ARG RAILS_ROOT=/app
ARG BUILD_PACKAGES="build-base curl-dev git"
ARG DEV_PACKAGES="postgresql-dev yaml-dev zlib-dev nodejs yarn"
ARG RUBY_PACKAGES="tzdata"
ENV RAILS_ENV=production
ENV NODE_ENV=production
ENV BUNDLE_APP_CONFIG="$RAILS_ROOT/.bundle"
WORKDIR $RAILS_ROOT
# install packages
RUN apk update \
    && apk upgrade \
    && apk add --update --no-cache $BUILD_PACKAGES $DEV_PACKAGES \
       $RUBY_PACKAGES
COPY Gemfile* package.json yarn.lock ./
RUN bundle config --global frozen 1 \
    && bundle install --path=vendor/bundle
RUN yarn install
COPY . .
RUN bin/rails assets:precompile
############### Build step done ###############
FROM ruby:2.5.1-alpine
ARG RAILS_ROOT=/app
ARG PACKAGES="tzdata postgresql-client nodejs bash"
ENV RAILS_ENV=production
ENV BUNDLE_APP_CONFIG="$RAILS_ROOT/.bundle"
WORKDIR $RAILS_ROOT
# install packages
RUN apk update \
    && apk upgrade \
    && apk add --update --no-cache $PACKAGES
COPY --from=build-env $RAILS_ROOT $RAILS_ROOT
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

这将尺寸减小了一半!

REPOSITORY          TAG  SIZE
small-docker-images  v3  360MB

这大约是我理想的docker大小,但是仍然可以进行一些清理以进一步减小大小。

3.在构建过程中删除不必要的文件

一些在开发中使用的文件从未在生产中使用,下面是一些示例:

1. app/assets vendor/assets node_modules - If you precompile your assets/webpack, these folders become irrelevant in prod
2. tmp/cache spec are also not needed in production
3. remove the gems cache and *.c and *.o files

删除这些文件后,这是我的新Dockerfile:

FROM ruby:2.5.1-alpine AS build-env
ARG RAILS_ROOT=/app
ARG BUILD_PACKAGES="build-base curl-dev git"
ARG DEV_PACKAGES="postgresql-dev yaml-dev zlib-dev nodejs yarn"
ARG RUBY_PACKAGES="tzdata"
ENV RAILS_ENV=production
ENV NODE_ENV=production
ENV BUNDLE_APP_CONFIG="$RAILS_ROOT/.bundle"
WORKDIR $RAILS_ROOT
# install packages
RUN apk update \
    && apk upgrade \
    && apk add --update --no-cache $BUILD_PACKAGES $DEV_PACKAGES $RUBY_PACKAGES
COPY Gemfile* package.json yarn.lock ./
# install rubygem
COPY Gemfile Gemfile.lock $RAILS_ROOT/
RUN bundle config --global frozen 1 \
    && bundle install --without development:test:assets -j4 --retry 3 --path=vendor/bundle \
    # Remove unneeded files (cached *.gem, *.o, *.c)
    && rm -rf vendor/bundle/ruby/2.5.0/cache/*.gem \
    && find vendor/bundle/ruby/2.5.0/gems/ -name "*.c" -delete \
    && find vendor/bundle/ruby/2.5.0/gems/ -name "*.o" -delete
RUN yarn install --production
COPY . .
RUN bin/rails webpacker:compile
RUN bin/rails assets:precompile
# Remove folders not needed in resulting image
RUN rm -rf node_modules tmp/cache app/assets vendor/assets spec
############### Build step done ###############
FROM ruby:2.5.1-alpine
ARG RAILS_ROOT=/app
ARG PACKAGES="tzdata postgresql-client nodejs bash"
ENV RAILS_ENV=production
ENV BUNDLE_APP_CONFIG="$RAILS_ROOT/.bundle"
WORKDIR $RAILS_ROOT
# install packages
RUN apk update \
    && apk upgrade \
    && apk add --update --no-cache $PACKAGES
COPY --from=build-env $RAILS_ROOT $RAILS_ROOT
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

大小约:

REPOSITORY           TAG    SIZE
small-docker-images  v4     162MB

从1.5G缩小到162MB,减少很多。

构建小型Docker容器可以提高build/pull的性能以及应用程序的安全性。通过利用小型基础镜像和多步骤构建模式,可以轻松开始减少rails docker映像的大小。

0条评论 顺序楼层
请先登录再回复