【问题标题】:docker-compose.yml not working for rails appdocker-compose.yml 不适用于 Rails 应用程序
【发布时间】:2020-09-14 15:05:00
【问题描述】:

我开发了一个使用 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"]

用于工作的 Dockerfile 的 startup.sh

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-rails docker kubernetes docker-compose


    【解决方案1】:

    您也应该在第二个 Dockerfile 中使用 CMD,然后它可以被 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
    

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

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

    【讨论】:

    • 我已经进行了您提到的更改,我可以看到 sidekiq 在 sidekiq 容器中运行,但 rails db:migrate 没有运行。在 startup.sh @DavidMaze 中提到过
    • 您认为什么时候应该运行迁移,这没有发生? (你不能在 Dockerfile 中运行它。)
    猜你喜欢
    • 2017-03-27
    • 2018-03-09
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 2019-01-31
    • 2015-12-24
    相关资源
    最近更新 更多