首页 > 解决方案 > docker-compose.yml 不适用于 Rails 应用程序

问题描述

我开发了一个使用 Redis、sidekiq 和 mysql2 的简单 rails 应用程序。我正在尝试使用 docker-compose 运行该应用程序。我写了一个运行良好的 docker-compose.yml。我对无法正常工作的 docker 文件进行了一些更改,当我看到日志时,webapp 容器正在以退出代码 1 退出。

这些是我的文件

Dockerfile

FROM ubuntu:16.04

ENV RUBY_MAJOR="2.6" \
    RUBY_VERSION="2.6.3" \
    RUBYGEMS_VERSION="3.0.8" \
    BUNDLER_VERSION="1.17.3" \
    RAILS_VERSION="5.2.1" \
    RAILS_ENV="production" \
    GEM_HOME="/usr/local/bundle"
ENV BUNDLE_PATH="$GEM_HOME" \
    BUNDLE_BIN="$GEM_HOME/bin" \
    BUNDLE_SILENCE_ROOT_WARNING=1 \
    BUNDLE_APP_CONFIG="$GEM_HOME"

ENV PATH="$BUNDLE_BIN:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH"

USER root
RUN apt-get update && \
      apt-get -y install sudo
RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    addgroup --gid 1024 stars && \
    useradd -G stars,sudo -d /home/user --shell /bin/bash -m user
RUN mkdir -p /usr/local/etc \
    && echo 'install: --no-document' >> /usr/local/etc/gemrc \
    && echo 'update: --no-document' >> /usr/local/etc/gemrc

USER user
RUN sudo apt-get -y install --no-install-recommends vim make gcc zlib1g-dev autoconf build-essential libssl-dev libsqlite3-dev \
    curl htop unzip mc openssh-server openssl bison libgdbm-dev ruby git libmysqlclient-dev tzdata mysql-client
    
RUN sudo rm -rf /var/lib/apt/lists/* \
    && sudo curl -fSL -o ruby.tar.gz "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz" \
    && sudo mkdir -p /usr/src/ruby \
    && sudo tar -xzf ruby.tar.gz -C /usr/src/ruby --strip-components=1 \
    && sudo rm ruby.tar.gz

USER root
RUN cd /usr/src/ruby \
    && { sudo echo '#define ENABLE_PATH_CHECK 0'; echo; cat file.c; } > file.c.new && mv file.c.new file.c \
    && autoconf \
    && ./configure --disable-install-doc

USER user
RUN cd /usr/src/ruby \
    && sudo make -j"$(nproc)" \
    && sudo make install \
    && sudo gem update --system $RUBYGEMS_VERSION \
    && sudo rm -r /usr/src/ruby
RUN sudo gem install bundler --version "$BUNDLER_VERSION"

RUN sudo mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
    && sudo chmod 777 "$GEM_HOME" "$BUNDLE_BIN" \
    && sudo gem install rails --version "$RAILS_VERSION"
RUN mkdir -p ~/.ssh && \
    chmod 0700 ~/.ssh && \
    ssh-keyscan github.com > ~/.ssh/known_hosts
ARG ssh_pub_key
ARG ssh_prv_key
RUN echo "$ssh_pub_key" > ~/.ssh/id_rsa.pub && \
    echo "$ssh_prv_key" > ~/.ssh/id_rsa && \
    chmod 600 ~/.ssh/id_rsa.pub && \
    chmod 600 ~/.ssh/id_rsa
USER root
RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
RUN apt-get install -y nodejs
USER user
WORKDIR /data
RUN sudo mkdir /data/checklist
WORKDIR /data/checklist
ADD Gemfile Gemfile.lock ./
RUN sudo chown -R user /data/checklist
RUN bundle install
ADD . .
RUN sudo chown -R user /data/checklist
EXPOSE 3001
ENV RAILS_SERVE_STATIC_FILES true
ENV RAILS_LOG_TO_STDOUT true
RUN chmod +x ./config/docker/compile.sh && ./config/docker/compile.sh
CMD ["bundle", "exec", "rails", "s", "-p", "3001"]

编译.sh

bundle exec rake assets:precompile
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:create db:migrate
echo "Assets Pre-compiled!"

这是我的 docker-compose.yml

version: '3'
services: 
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: "list"
      MYSQL_ROOT_PASSWORD: "Mission2019"
      MYSQL_USERNAME: "root"
  webapp:
    build: .
    ports:
      - '3001:3001'
    volumes:
      - '.:/data/checklist'
    depends_on:
      - db
      - redis
    command: rails db:migrate
    environment:
      DB_USERNAME: "root"
      DB_PASSWORD: "Mission2019"
      DB_DATABASE: "list"
      DB_PORT: 3306
      DB_HOST: db
      RAILS_ENV: production 
      RAILS_MAX_THREADS: 5
  redis:
    image: redis:4.0-alpine
    command: redis-server
    ports:
      - '6379:6379'
  sidekiq:
    build: .
    command: bundle exec sidekiq -C config/sidekiq.yml
    depends_on:
      - "db"
      - "redis"

工作 Dockerfile

FROM ubuntu:16.04

ENV RUBY_MAJOR="2.6" \
    RUBY_VERSION="2.6.3" \
    RUBYGEMS_VERSION="3.0.8" \
    BUNDLER_VERSION="1.17.3" \
    RAILS_VERSION="5.2.1" \
    RAILS_ENV="production" \
    GEM_HOME="/usr/local/bundle"
ENV BUNDLE_PATH="$GEM_HOME" \
    BUNDLE_BIN="$GEM_HOME/bin" \
    BUNDLE_SILENCE_ROOT_WARNING=1 \
    BUNDLE_APP_CONFIG="$GEM_HOME"

ENV PATH="$BUNDLE_BIN:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH"

USER root
RUN apt-get update && \
      apt-get -y install sudo
RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    addgroup --gid 1024 stars && \
    useradd -G stars,sudo -d /home/user --shell /bin/bash -m user
RUN mkdir -p /usr/local/etc \
    && echo 'install: --no-document' >> /usr/local/etc/gemrc \
    && echo 'update: --no-document' >> /usr/local/etc/gemrc

USER user
RUN sudo apt-get -y install --no-install-recommends vim make gcc zlib1g-dev autoconf build-essential libssl-dev libsqlite3-dev \
    curl htop unzip mc openssh-server openssl bison libgdbm-dev ruby git libmysqlclient-dev tzdata mysql-client
    
RUN sudo rm -rf /var/lib/apt/lists/* \
    && sudo curl -fSL -o ruby.tar.gz "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz" \
    && sudo mkdir -p /usr/src/ruby \
    && sudo tar -xzf ruby.tar.gz -C /usr/src/ruby --strip-components=1 \
    && sudo rm ruby.tar.gz

USER root
RUN cd /usr/src/ruby \
    && { sudo echo '#define ENABLE_PATH_CHECK 0'; echo; cat file.c; } > file.c.new && mv file.c.new file.c \
    && autoconf \
    && ./configure --disable-install-doc

USER user
RUN cd /usr/src/ruby \
    && sudo make -j"$(nproc)" \
    && sudo make install \
    && sudo gem update --system $RUBYGEMS_VERSION \
    && sudo rm -r /usr/src/ruby
RUN sudo gem install bundler --version "$BUNDLER_VERSION"

RUN sudo mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
    && sudo chmod 777 "$GEM_HOME" "$BUNDLE_BIN" \
    && sudo gem install rails --version "$RAILS_VERSION"
RUN mkdir -p ~/.ssh && \
    chmod 0700 ~/.ssh && \
    ssh-keyscan github.com > ~/.ssh/known_hosts
ARG ssh_pub_key
ARG ssh_prv_key
RUN echo "$ssh_pub_key" > ~/.ssh/id_rsa.pub && \
    echo "$ssh_prv_key" > ~/.ssh/id_rsa && \
    chmod 600 ~/.ssh/id_rsa.pub && \
    chmod 600 ~/.ssh/id_rsa
USER root
RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
RUN apt-get install -y nodejs
USER user
WORKDIR /data
RUN sudo mkdir /data/checklist
WORKDIR /data/checklist
ADD Gemfile Gemfile.lock ./
RUN sudo chown -R user /data/checklist
RUN bundle install
ADD . .
RUN sudo chown -R user /data/checklist
EXPOSE 3001
ENV RAILS_SERVE_STATIC_FILES true
ENV RAILS_LOG_TO_STDOUT true
ENTRYPOINT ["sh", "./config/docker/startup.sh"]

startup.sh 用于工作的 Dockerfile

kill -9 `cat /data/checklist/tmp/pids/server.pid`
bundle exec rake assets:precompile
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:create db:migrate
rails s -p 3001 -b 0.0.0.0 -e PRODUCTION
echo "Assets Pre-compiled!"

更改 Dockerfile 的原因是,因为我使用的是 sidekiq,并且我希望 sidekiq 一起在另一个单独的容器中运行。如果我在 docker-compose.yml 中给出命令选项,它不会启动,bundle exec sidekiq -C config/sidekiq.yml也不会在 sidekiq 容器中运行。

我有同一个应用程序的 kubernetes yaml 文件。那里也面临同样的问题。我无法为 sidekiq pod 覆盖 YAML 中的入口点指令。

如果需要任何其他信息,请告诉我。

标签: ruby-on-railsdockerkubernetesdocker-compose

解决方案


您也应该CMD在第二个 Dockerfile 中使用,然后它可以被 Docker Compose 覆盖command:

# CMD, not ENTRYPOINT
CMD ["sh", "./config/docker/startup.sh"]

的一个常见用途ENTRYPOINT是作为一个包装程序,它执行一些环境或其他首次设置,然后执行CMD作为命令行参数的其余部分传入的那些。然后您可以单独替换命令部分,同时保留设置部分。在 Ruby 环境bundle exec ...中具有正确的语义,因此您还可以考虑:

# Note: MUST be JSON-array syntax
ENTRYPOINT ["bundle", "exec"]
# Can be either string or JSON-array form
CMD ["./config/docker/startup.sh"]
version: '3.8'
services:
  webapp:
    build: .
    # Use default CMD/ENTRYPOINT from image
  sidekiq:
    build: .
    # Overrides CMD, leaves ENTRYPOINT in place
    command: sidekiq -C config/sidekiq.yml

有一个单独的 Composeentrypoint:覆盖,但您应该很少需要它。

(您的 Dockerfile 可以简单得多。一般情况下,您不需要配置sudo或用户密码,并且 Dockerfiles 默认以 root 身份运行,除非您明确使用USER切换当前用户 ID。将 ssh 凭据添加到 Dockerfile 中它们可以很简单docker cp'd out 也不是最佳实践。还可以考虑使用 Docker Hubruby映像而不是从源代码构建自己的映像。)


推荐阅读