优化Dockerfile、缩小镜像大小,加快容器的启停速度
在上一篇文章《docker-compose部署Rails应用》中,用docker-compose配置了应用集,镜像的构建用了centos:6.10,使用rbenv安装了ruby环境,这样的方式多此一举,而且严重影响镜像的大小,容器的性能,下面我们用更好的方式再做一次。
镜像对比
首先对比下几个基础镜像的大小:
23 MB ruby2.5-alpine
70 MB centos6.10
之前构建的镜像大小是780MB,所以基础镜像之间的差别不会很大,而错误的构建步骤会让镜像的大小天差地别。
下面是此次的大小:
镜像构建
- 源码需要做好静态文件的编译等工作,可以配合各类持续集成工具预先做好。
- 镜像中只安装必要的库,如果不清楚只能一个一个试错,apk的buildbase基本胜任编译工作,安装完卸载无用库及缓存文件。
- 复杂应用需要拆分,镜像尽量保持在200MB左右,这样在K8s横向扩展时才能逼近秒级。
- 将各类软件安装的源改为国内。
- docker build -t rails-app . –no-cache,在调试过程中可不用缓存,出错难定位。
- 注意时区设置。
文件目录如下:
FROM ruby:2.5-alpine
WORKDIR /app
COPY code /app/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
apk add --no-cache make gcc g++ tzdata libc-dev libxml2 libxslt postgresql-dev nodejs && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/ && \
gem install bundler -N && \
bundle config mirror.https://rubygems.org https://gems.ruby-china.com && \
bundle install --without development test && \
apk del make gcc g++ tzdata
docker-compose相关配置
docker-compose.yml
version: "3"
services:
rails-app:
image: rails-app
command: puma -C config/puma.rb
volumes:
# 共享文件需要外挂出来,和以前cap部署的shared差不多。
# 配置文件在调试过程中一般挂出来,修改完重启服务方便调试,不用每次重新打包。
- ./app/logs:/app/logs
- ./app/config:/app/config
- ./app/public:/app/public
depends_on:
- nginx
- db
nginx:
image: nginx
volumes:
- ./nginx/logs:/var/log/nginx
ports:
- "80:80"
volumes:
- ./nginx/configs/app.conf:/etc/nginx/nginx.conf
- ./app/public:/app/public
db:
image: postgres:10-alpine
restart: always
ports:
- 5432:5432
environment:
# 在.env文件中设置
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- ./postgres:/var/lib/postgresql/data
.env
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=123456
app/config/puma.rb
directory '/app'
rackup "/app/config.ru"
environment 'production'
tag ''
pidfile "/app/public/puma.pid"
state_path "/app/public/puma.state"
stdout_redirect '/app/logs/puma_error.log', '/app/logs/puma_access.log', true
threads 4,16
bind 'unix:///app/public/puma.sock'
workers 1
preload_app!
on_restart do
puts 'Refreshing Gemfile'
ENV["BUNDLE_GEMFILE"] = ""
end
这里用了socket方式没有暴露端口,nginx做反向代理。
app.conf
upstream railsapp {
server unix:/app/public/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost; # change to match your URL
root /app/public;
location / {
proxy_pass http://railsapp;
proxy_set_header Host $host:88;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 1024m;
# add_header Access-Control-Allow-Origin *;
}
location ~* ^/(uploads|assets|public)/ {
expires 1y;
add_header Cache-Control public;
gzip_static on;
add_header Last-Modified "";
add_header ETag "";
break;
}
}
数据库相关
pg_hba.conf
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 0.0.0.0/0 trust
# IPv6 local connections:
host all all 0.0.0.0/0 trust
app/config/database.yml
default: &default
adapter: postgresql
encoding: unicode
host: db
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
production:
<<: *default
database: app_production
username: postgres
password: <%= Rails.application.credentials.db[:password] %>
初始化数据库
docker-compose run rails-app rake db:create RAILS_ENV=production
docker-compose run rails-app rake db:migrate RAILS_ENV=production
docker-compose run rails-app rake db:seed RAILS_ENV=production
完成