代码之家  ›  专栏  ›  技术社区  ›  josegp

同一Dockerfile上的不同条件

  •  0
  • josegp  · 技术社区  · 3 年前

    我有一个Dockerfile,其中包含一些我想有条件使用的命令:

    1. FROM + image_name (我有一个M1芯片MacOS,所以我需要添加 --platform=linux/amd64 但我想部署在不需要它的AWS EC2 linux实例中)
    2. 在生产中,我希望使用nginx运行我的项目,因此我希望Dockerfile以此结束 RUN mkdir -p tmp/sockets . 但对于测试,我不需要nginx,所以我希望我的Dockerfile以这个结尾
    # Expose port 
    EXPOSE 3000
    
    # Start rails
    CMD ["rails", "server", "-b", "0.0.0.0"]
    

    我想用 multi stage dockerfile 解决 FROM image 问题,但由此产生的Dockerfile相当长,因为除了 来自图像 部分 对于 nginx 我想使用shell脚本,但我不知道如何编写公开端口和启动rails的最终命令。 以下是文件:

    run_dockerfile.sh

    #!/bin/bash
    
    if [ ${RUN_DOCKERFILE} = "PROD" ]; then 
        mkdir -p tmp/sockets
    else
        ????
    fi
    

    我的 Dockerfile 如下所示:

    # Start from the official ruby image
    # To run Dockerfile with arm64 architecture (M1 chip MacOS for example)
    FROM --platform=linux/amd64 ruby:2.6.6 AS ARM64
    
    # Set environment
    ARG BUILD_DEVELOPMENT
    # if --build-arg BUILD_DEVELOPMENT=1, set RAILS_ENV to 'development' or set to null otherwise.
    ENV RAILS_ENV=${BUILD_DEVELOPMENT:+development}
    # if RAILS_ENV is null, set it to 'production' (or leave as is otherwise).
    ENV RAILS_ENV=${RAILS_ENV:-production}
    
    # Update and install JS & DB
    RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
    
    # Create a directory for the application and use it
    RUN mkdir /myapp
    WORKDIR /myapp
    
    # Gemfile and lock file need to be present, they'll be overwritten immediately
    COPY Gemfile /myapp/Gemfile
    COPY Gemfile.lock /myapp/Gemfile.lock
    
    # Install gem dependencies
    RUN gem install bundler:2.2.32
    RUN bundle install
    RUN curl https://deb.nodesource.com/setup_12.x | bash
    ADD https://dl.yarnpkg.com/debian/pubkey.gpg /tmp/yarn-pubkey.gpg
    RUN apt-key add /tmp/yarn-pubkey.gpg && rm /tmp/yarn-pubkey.gpg
    RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
    RUN apt-get update -qq && apt-get install -y yarn  && apt-get install -y npm
    RUN yarn add bootstrap
    
    COPY . /myapp
    
    # So that webpacker compiles
    RUN yarn config set ignore-engines true
    RUN rm -rf bin/webpack*
    RUN rails webpacker:install
    RUN bundle exec rails webpacker:compile
    RUN bundle exec rake assets:precompile
    
    # This script runs every time the container is created, necessary for rails
    COPY entrypoint.sh /usr/bin/
    RUN chmod +x /usr/bin/entrypoint.sh
    ENTRYPOINT ["entrypoint.sh"]
    
    
    # Run run_dockerfile.sh
    COPY run_dockerfile.sh run_dockerfile.sh
    RUN chmod u+x run_dockerfile.sh && ./run_dockerfile.sh
    
    
    ##################################################
    
    # Start from the official ruby image
    # To run Dockerfile without arm64 architecture
    FROM ruby:2.6.6 AS AMD64
    
    # Set environment
    ARG BUILD_DEVELOPMENT
    # if --build-arg BUILD_DEVELOPMENT=1, set RAILS_ENV to 'development' or set to null otherwise.
    ENV RAILS_ENV=${BUILD_DEVELOPMENT:+development}
    # if RAILS_ENV is null, set it to 'production' (or leave as is otherwise).
    ENV RAILS_ENV=${RAILS_ENV:-production}
    
    # Update and install JS & DB
    RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
    
    # Create a directory for the application and use it
    RUN mkdir /myapp
    WORKDIR /myapp
    
    # Gemfile and lock file need to be present, they'll be overwritten immediately
    COPY Gemfile /myapp/Gemfile
    COPY Gemfile.lock /myapp/Gemfile.lock
    
    # Install gem dependencies
    RUN gem install bundler:2.2.32
    RUN bundle install
    RUN curl https://deb.nodesource.com/setup_12.x | bash
    ADD https://dl.yarnpkg.com/debian/pubkey.gpg /tmp/yarn-pubkey.gpg
    RUN apt-key add /tmp/yarn-pubkey.gpg && rm /tmp/yarn-pubkey.gpg
    RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
    RUN apt-get update -qq && apt-get install -y yarn  && apt-get install -y npm
    RUN yarn add bootstrap
    
    COPY . /myapp
    
    # So that webpacker compiles
    RUN yarn config set ignore-engines true
    RUN rm -rf bin/webpack*
    RUN rails webpacker:install
    RUN bundle exec rails webpacker:compile
    RUN bundle exec rake assets:precompile
    
    # This script runs every time the container is created, necessary for rails
    COPY entrypoint.sh /usr/bin/
    RUN chmod +x /usr/bin/entrypoint.sh
    ENTRYPOINT ["entrypoint.sh"]
    
    # Run run_dockerfile.sh
    COPY run_dockerfile.sh run_dockerfile.sh
    RUN chmod u+x run_dockerfile.sh && ./run_dockerfile.sh
    

    我有没有办法 .sh 或者,对于正确的方法有什么建议吗?非常感谢。

    0 回复  |  直到 3 年前
        1
  •  0
  •   David Maze    3 年前

    从您描述问题的方式来看,您根本不需要太多特殊情况。

    一个重要的细节是,很容易覆盖图像的 CMD 运行容器时。如果你有 two Compose files ,例如,您可以只设置服务的 command:

    # docker-compose.yml
    version: '3.8'
    services:
      myapp:
        image: registry.example.com/myapp:${MYAPP_TAG:-latest}
        ports: ['3000:80']
    
    # docker-compose.override.yml
    # for developer use
    version: '3.8'
    services:
      myapp:
        build: .
        command: rails server -b 0.0.0.0 -p 80
    

    您列出的其他变体应该无关紧要。如果你建立你的形象,你应该得到一致的结果 FROM --platform=linux/amd64 在x86-64主机上,显式指定本机平台; RUN mkdir 你不使用的目录是无害的。一个不一致的地方似乎是集装箱港口,但您可以明确地看出 rails server 要使用哪个端口进行匹配。我会在所有环境中使用相同的图像。

    FROM --platform=linux/amd64 ruby:2.6.6 # even on an Intel/AMD host system
    ...
    RUN mkdir tmp/sockets                  # even if it's unused
    CMD ["nginx", "-g", "daemon off;"]     # can be overridden when the container runs