部署 用 Docker 构建开发环境

heroyct · 2018年10月15日 · 最后由 IChou 回复于 2018年10月17日 · 9015 次阅读

最近用 docker 进行了开发环境的构建

本文主要介绍如何使用 docker 进行开发环境的构建

为什么要用 docker 构建开发环境

目前比较主流的方式应该是 vagrant 和 docker,对优缺点进行了比较

1. vagrant

优点

  • 设置比较简单

缺点

  • 比较耗费磁盘,内存等资源
  • 首次启动 (provision) 的时间比较长
  • 启动的时间比较慢

2. docker

优点

  • 比较节省资源
  • 首次启动 (build image) 比较快
    • 目前项目 vagrant 要用几十分钟,docker 只用几分钟
  • 启动非常快
    • vagrant 要几分钟,用 docker 只要几秒钟

备注:消耗的时间是我目前项目的时间,每个项目有所不同

缺点

  • 学习成本相对较高,尤其是 deploy 到生产环境的时候需要一定的学习成本

docker 相关术语

  • Image(镜像)
    • 一个文件系统,里面包含了需要运行在 Container 的所有东西
  • Container(容器)
    • 镜像的启动实例
  • Dockerfile(构建镜像的配置文件)
  • Compose(一个工具 使构建多个容器变得更加容易)

具体说明可以在这里查看
https://docs.docker.com/v17.09/engine/userguide/storagedriver/imagesandcontainers/

本次构建的开发环境

  • centos7
  • ruby
  • rails
  • mysql

准备工作

  • 准备一台 mac,windows 的话可以先用 virtualBox 开个虚拟机
  • 准备一个 rails 程序
  • 安装 docker for mac
  • 安装 docker-compose

构建的步骤

最后的相关文件结构,下面逐步讲解每个文件的内容

dockerfile/
├── app
│   ├── Dockerfile
│   └── scripts
│       └── build.sh
└── mysql
    ├── Dockerfile
    └── conf
        └── my.cnf
├── build_all.sh
docker-compose.yml

1. web 服务器镜像设置

设置 dockerfile

# dockerfile/app/Dockerfile

# OS的镜像可以在这里查看 https://hub.docker.com/_/centos/
FROM centos:centos7

# set operator user env
# 追加一个普通用户book来进行bundle install
ENV LANG=en_US.UTF-8 OPERATOR_USER=book OPERATOR_GROUP=book
ENV OPERATOR_UID=500 OPERATOR_GID=500
ENV RUBY_VERSION=2.5.1

# 在这里进行安装ruby等详细设置
COPY scripts /tmp/scripts
RUN bash -x /tmp/scripts/build.sh

# 设置进入docker以后的默认目录
WORKDIR /www/ruby-book/

编写详细设置用的脚本

# dockerfile/app/scripts/build.sh

#!/bin/bash
# -e stop when error occurred
# -x show executed command
set -ex

# add book user, book group
groupadd -g ${OPERATOR_GID} ${OPERATOR_GROUP}
useradd --create-home -s /bin/bash -u ${OPERATOR_UID} -g ${OPERATOR_GID} ${OPERATOR_USER}

# add server folder use ruby user
mkdir -p /www/ruby-book
chown ${OPERATOR_UID}:${OPERATOR_GID} /www/ruby-book

# install package
yum update -y
# 不是全部都需要的,可以选择安装自己想要装的工具
yum install -y git make gcc bzip2 openssl-devel readline-devel zlib-devel curl-devel mysql-devel which tar wget sudo libmysqlclient-dev

# install rbenv ruby-build
git clone git://github.com/sstephenson/rbenv.git /usr/local/rbenv
git clone git://github.com/sstephenson/ruby-build.git /usr/local/rbenv/plugins/ruby-build

echo 'export RBENV_ROOT="/usr/local/rbenv"' >> /etc/profile.d/rbenv.sh
echo 'export PATH="$RBENV_ROOT/bin:$RBENV_ROOT/shims:$PATH"' >> /etc/profile.d/rbenv.sh
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh

# install ruby
source /etc/profile.d/rbenv.sh
rbenv install ${RUBY_VERSION}
rbenv rehash
rbenv global ${RUBY_VERSION}

# install bundler
gem install bundler

2. mysql 镜像设置

设置 dockerfile

# dockerfile/mysql/Dockerfile

FROM mysql:5.7.22

COPY conf/my.cnf /etc/mysql/conf.d/app.cnf

创建 mysql 设置文件

# dockerfile/mysql/conf/my.cnf

[client]
socket = /tmp/mysql.sock

[mysql]
default-character-set=utf8mb4

[mysqld]
explicit_defaults_for_timestamp = true
sql_mode = TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY

character_set_server = utf8mb4
datadir = /var/lib/mysql

3. 编译镜像

使用 docker build 命令来进行 build 镜像文件
因为要 build 两个镜像所以写了个脚本来一次行进行 build

# dockerfile/build_all.sh

#!/bin/bash

set -ex
DIRNAME=$(dirname "$(pwd)/${0}")
RAILS_ROOT=${DIRNAME}/../
cd ${RAILS_ROOT}
cd dockerfile/

IMAGE_REPOSITORY=book/book
cd app
APP_IMAGE="7_20180531"
docker build --force-rm -t ${IMAGE_REPOSITORY}:app-centos-${APP_IMAGE} .

cd ../mysql
docker build --rm -t mysql:5.7.22 .

用上面的脚本编译所有的镜像

$ ./build_all.sh

用 docker images 来查看生成的镜像文件

$ docker images

REPOSITORY          TAG                     IMAGE ID            CREATED             SIZE
mysql               5.7.22                  1da5a40f1204        15 minutes ago      372MB
book/book           app-centos-7_20180531   6004010a3f19        16 minutes ago      614MB
centos              centos7                 75835a67d134        4 days ago          200MB

4. 设置 docker-compose

设置 docker-compose 来启动 docker container

# docker-compose.yml

version: '3'

services:
  app:
    environment:
      RAILS_DATABASE_HOST: db

    image: book/book:app-centos-7_20180531
    volumes:
      - ./:/www/ruby-book:cached
      - app-bundle:/www/ruby-book/vendor/bundle
      - app-tmp:/www/ruby-book/tmp

    ports:
      - 3000:3000
    tty: true

  db:
    image: mysql:5.7.22
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
    volumes:
      - db-data:/var/lib/mysql
      - db-log:/var/log/mysql
      - ./dockerfile/mysql/conf/my.cnf:/etc/mysql/conf.d/app.cnf
    ports:
      - 3306:3306

volumes:
  app-bundle:
  app-tmp:
  db-data:
  db-log:

镜像重新 build 以后还希望保留的文件都可以设置成 volumes、这样镜像重新 build 以后也会保留下来

可以使用 volume 命令来查看和删除

$ docker volume ls
$ docker volume rm {volume name}

5. how to use

# build all images
$ cd dockerfile/
$ ./build_all.sh

# create container run backgroud
$ docker-compose -f docker-compose.yml up -d

# 进入web服务器
$ docker-compose exec --user book app bash  # book用户
$ docker-compose exec app bash # root用户

# bundle install , create db
$ bundle install --path vendor/bundle
$ bundle exec rake db:create
$ bundle exec rake db:migrate

测试

访问以下页面呈现欢迎界面就说明完成了

http://localhost:3000/

参考文章

希望再发一个 docker 部署多机 + 负载均衡的攻略

@ad583255925 @yukihiro_matz
目前项目用的是 AWS ECS + CircleCI 来部署,负载均衡是 ELB

把第五步how to use 整理成一个脚本,在 Dockerfile 中用 ENTRYPOINT/CMD 触发,再加上一个平滑替换容器的脚本,就完美了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号