我目前正在将Rails应用程序部署到单个EC2实例。我是Docker的新手,所以我可能会缺少一些明显的东西。我有2个Dockerfile-应用程序(Rails应用程序)和Web(nginx):
docker
├── app
│ └── Dockerfile
└── web
├── Dockerfile
└── nginx.conf
docker / app / Dockerfile:
FROM ruby:2.5.8
RUN apt-get update && \
apt-get install -y \
curl \
vim \
netcat \
less \
default-mysql-client \
--no-install-recommends && \
rm -rf /var/lib/apt/lists/*
SHELL ["/bin/bash", "--login", "-i", "-c"]
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
RUN source /root/.bashrc && nvm install 10.19.0
SHELL ["/bin/bash", "--login", "-c"]
RUN npm install -g yarn
RUN yarn install --check-files
RUN mkdir -p /home/ubuntu/zhxword
ENV RAILS_ROOT /home/ubuntu/zhxword
EXPOSE 3000
WORKDIR $RAILS_ROOT
ADD Gemfile $RAILS_ROOT/Gemfile
ADD Gemfile.lock $RAILS_ROOT/Gemfile.lock
ADD . $RAILS_ROOT
RUN gem install bundler
RUN bundle install
RUN bundle exec rake assets:precompile
docker / web / Dockerfile
FROM nginx
RUN apt-get update -qq && apt-get -y install apache2-utils
ENV RAILS_ROOT /var/www/app_name
WORKDIR $RAILS_ROOT
RUN mkdir log
COPY public public/
COPY docker/web/nginx.conf /tmp/docker.nginx
RUN envsubst '$RAILS_ROOT' < /tmp/docker.nginx > /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]
MySQL服务器通过docker-compose.yml引入:
version: '3.1'
volumes:
db_data: {}
# This part is explained below the file
services:
db:
image: mysql:5.6
volumes:
- db_data:/var/lib/mysql
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --init-connect='SET NAMES UTF8;' --innodb-flush-log-at-trx-commit=0
environment:
MYSQL_ROOT_PASSWORD: XXXXXX
MYSQL_DATABASE: zhxword_production
MYSQL_USER: zhxword
MYSQL_PASSWORD: XXXXXX
app:
build:
context: .
dockerfile: ./docker/app/Dockerfile
command: /bin/sh -c "bin/wait-for db:3306 -- rm -f /home/ubuntu/zhxword/tmp/pids/server.pid && bundle exec rails server puma -p 3000"
volumes:
- $PWD:/zhxword
ports:
- "3000:3000"
links:
- "db:database"
env_file:
- .env.production
depends_on:
- db
web:
build:
context: .
dockerfile: ./docker/web/Dockerfile
depends_on:
- app
ports:
- "80:80"
我正在使用docker-machine
发布到AWS:
docker-machine create --driver amazonec2 --amazonec2-instance-type "t2.micro" production
docker-machine env production
eval $(docker-machine env production)
docker-compose build
docker-compose up -d
问题
针对AWS目标运行docker-compose build
大约需要1小时20分钟。
我尝试了t2.micro
和t2.medium
实例类型,这似乎花费了相同的时间。应用程序容器中特别慢的步骤之一是安装具有本机扩展的sassc 2.3.0 ,但是通常应用程序和Web容器都需要很长时间。
在本地(在笔记本电脑上)运行docker-compose build
的速度要快得多-总共大约7分钟。针对AWS目标运行docker-compose up
只需要一两分钟。
我可以采用哪些策略来加快构建过程?
答案 0 :(得分:2)
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
2.7.1-alpine3.11
。
答案 1 :(得分:1)
您应该在本地构建映像,将其推送到Docker注册表(在AWS上下文中,考虑使用ECR),然后从EC2实例运行该映像。
在您的docker-compose.yml
文件中,您需要在本地执行的重要操作是为要构建的两个引用(ECR)外部存储库的图像添加image:
行。在本地,您可以像现在一样继续docker-compose build
和docker-compose up
。
app
容器具有绑定安装,该绑定安装将无法在远程EC2实例上运行(除非您在那里单独复制您的应用程序,这使使用Docker的原因之一无法解决)。在此处删除volumes:
。确保您的应用程序仍能按预期(本地)运行。
现在,您可以docker-compose push
构建的图像了。从build:
文件中删除docker-compose.yml
块,并以与现在相同的方式运行它。
我有两个原因可以立即想到您的构建速度很慢。 docker build
首先获取本地目录树(构建上下文),并将其通过Docker套接字发送到守护程序;在本地系统上,这将比远程系统快得多。第二个问题是t2
共享实例(尤其是t2.micro
)在许多应用程序中的功能不足,因此,如果您的yarn install
或Rails预编译步骤进行了大量工作,则这些工作可能会花费很多这种最小实例类型的时间要长得多。
答案 2 :(得分:0)
在尝试了多种方法之后,我发现了构建过程缓慢的根本原因。将其张贴在这里,以防其他人碰到它。
我的应用程序是Rails 6应用程序,Rails 6使用Webpacker作为JavaScript编译器。最初,我是在主机笔记本电脑上进行开发的。在开发过程中,Webpacker会在public/packs
中创建临时JS文件的 lot ,它不会自动修剪。我是通过在主机笔记本电脑中运行以下命令来发现这一点的:
$ du -skh *
4.0K Gemfile
8.0K Gemfile.lock
4.0K README.md
4.0K Rakefile
348K app
4.0K babel.config.js
36K bin
4.0K commit_message
148K config
4.0K config.ru
28K db
24K docker
4.0K docker-compose.yml
0B lib
3.1M log
8.0K misc
101M node_modules
4.0K package.json
4.0K postcss.config.js
136K public
0B storage
18M tmp
0B vendor
256K yarn-error.log
240K yarn.lock
在我的情况下,不需要1.2GB的内容,因为在生产中,JS文件是用RUN bundle exec rake assets:precompile
指令预编译的。 (注意:您可以通过运行bundle exec rails webpacker:clobber
强制Webpacker手动清除这些临时文件。)
ADD . $RAILS_ROOT
中的app/Dockerfile
命令将所有放入远程容器中-这就是为什么它这么慢的原因。
要解决此问题,我在.dockerignore
中添加了以下两行:
node_modules/*
public/packs/*
这告诉docker在执行ADD
命令时忽略这些路径。
通过这些更改,docker-compose build
步骤(当使用docker-machine
定位远程AWS实例时仅花费了51秒-大约是1小时20分钟!