Docker 为部署提供了便捷,能让新手快速部署复杂的服务器环境,并把环境保存下来。网上有许多 Docker 实践,本文实践的是如何利用 Docker 容器封装一个与代码配置分离的服务器环境,每次修改配置只需重启容器,无需重新建立镜像,并简单实现了多个站点部署。选择部署的环境是 Rails,基础镜像选用集成服务器环境的 phusion/passenger-ruby22,数据库选用 postgres
为了突出重点,部署没有涉及 mina 以及 puma 相关配置
apps # 服务器工作空间目录
|__ deploy # 部署配置文件目录
|__ |__ Dockerfile
|__ |__ docker.sh # 容器每次启动运行都会执行该脚本
|__ |__ docker-link.sh # 通过该文件使得容器启动执行脚本与镜像隔离,后面有文件内容
|__ |__ nginx.conf
|__ |__ nginx-env.conf
|__ |__ database.yml
|__ |__ secrets.yml
|__ |__ ...ddjh
|__ site_a # 网站源码目录
|__ site_b
|__ ...
上述目录结构需要事先在服务器中搭建好,我的操作步骤是建立在/home 目录下建立好 apps 目录后,在我们的工作目录 apps 里 git clone 相关网站;deploy 部署目录含相关服务器和密钥配置,下方写好后通过 scp 命令上传
# 以phusion/passenger-ruby22镜像为基础
FROM phusion/passenger-ruby22
# 设置项目目录
VOLUME ['/home/apps']
WORKDIR /home/apps
# 设置容器运行执行命令
CMD ["/sbin/my_init"]
# 开放80端口
EXPOSE 80
# 设置时区
RUN echo "Asia/Shanghai" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
# 设置当前环境变量
ENV HOME /root
# 设置rails环境为生产环境
ENV RAILS_ENV production
# 启动nginx
RUN rm -f /etc/service/nginx/down
# 增加初始化运行脚本
RUN mkdir -p /etc/my_init.d
COPY docker-link.sh /etc/my_init.d/docker-link.sh
RUN chmod +x /etc/my_init.d/docker-link.sh
# 修改国内源
RUN gem sources -r https://rubygems.org/ -a https://gems.ruby-china.org/
RUN bundle config mirror.https://rubygems.org https://gems.ruby-china.org
# RUN gem sources -r https://rubygems.org/ -a http://mirrors.aliyun.com/rubygems/
# RUN bundle config mirror.https://rubygems.org http://mirrors.aliyun.com/rubygems
# 清楚产生的缓存文件
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
#!/bin/bash
bash /home/apps/deploy/docker.sh
#!/bin/bash
echo '/*** 变量配置---------------:';
workdir='/home/apps'; # 工作空间目录,需要与Dockerfile文件的项目目录对应
# workdir='/var/www/apps'; # 其他类似工作空间目录
deployname='deploy'; # 部署目录名
sitearr=('site_a' 'site_b'); # 配置所有项目名
echo '/*** 配置nginx---------------:';
rm /etc/nginx/sites-enabled/default;
cp ${workdir}/${deployname}/nginx.conf /etc/nginx/sites-enabled/nginx.conf;
echo '/*** 添加环境文件---------------:';
cp ${workdir}/${deployname}/nginx-env.conf /etc/nginx/main.d/nginx-env.conf;
echo '/*** 遍历每个项目执行操作---------------:';
for site in ${sitearr[@]};
do
echo "/*** ${site}配置---------------:";
cd ${workdir}/${site};
bundle install;
rake assets:precompile;
rake db:create;
rake db:migrate;
rake db:seed;
done
# site_a
server {
listen 80;
root /home/apps/site_a/public;
server_name site_a.urlis.cn;
# 开启passenger
passenger_enabled on;
passenger_user root;
client_max_body_size 20M;
passenger_max_request_queue_size 0;
}
# site_b
server {
listen 80;
root /home/apps/site_b/public;
server_name site_b.urlis.cn;
# 开启passenger
passenger_enabled on;
passenger_user root;
client_max_body_size 20M;
passenger_max_request_queue_size 0;
}
# 暴露服务端口 这个示例中只有postgres服务,因此我们只需要暴露这个端口即可
env POSTGRES_PORT_5432_TCP_ADDR;
env POSTGRES_PORT_5432_TCP_PORT;
production:
<<: *default
database: site_production
host: <%= ENV['POSTGRES_PORT_5432_TCP_ADDR'] || 'localhost' %>
port: <%= ENV['POSTGRES_PORT_5432_TCP_PORT'] || '5432' %>
local$ ssh user@server;
server$ mkdir -p /home/apps;
server$ cd /home/apps;
server$ git clone https://github.com/pinewong/site_a;
server$ git clone https://github.com/pinewong/site_b;
...
local$ scp -r deploy user@server:/home/apps
server$ cd /home/apps/deploy
server$ docker pull postgres; docker pull phusion/passenger-ruby22;
server$ docker rm -f postgres; docker run --name postgres -p 5432:5432 -d postgres;
server$ docker rmi -f pinewong/passenger-ruby22; docker build -t pinewong/passenger-ruby22 .;
server$ docker rm -f web; docker run --name web --link postgres -v /home/apps:/home/apps -p 80:80 -d pinewong/passenger-ruby22;
server$ docker logs -f web;
最后等待终端的 log 日志输出,查看之前编写的 docker.sh 脚本执行情况。如果顺利,最后 nginx 服务器会启动成功。 以后有新项目上线测试时,只需要在服务器工作目录 clone 源码,然后添加 deploy/nginx.conf 配置,deploy/docker.sh 的 sitearr 数组变量值添加新项目名称,最后重启容器 (docker restart web)。 另外以后当修改配置文件,或新增 gem 时,也只需要执行容器容器命令
文章参考:gameFu's Blog