Tips: 下面的部分链接中带有小尾巴,谨点
去年的时候从阿里云捻过一次羊毛(云翼计划,如果愿意,可以是用我的阿里云推荐码,z9xy74
),如今一年已过,这个服务器也过期了,但是上面跑了一个微信企业号的应用在,由于有一直在使用的需求,不能停止,但是阿里云的羊毛是青岛节点,延迟高,而且现在到期了,默认变成了按流量付费,顿时觉得随时会少一套房子了。于是重新买了一个阿里云的华东节点,准备迁移过来,并且也准备把 DigitalOcean 上的部分应用迁移回国。
Docker 装好后,然后创建一个 docker 用户来专门管理 Docker 和存放一些配置文件。
sudo useradd -m -g docker -s /bin/bash docker
sudo su docker
mkdir -p ~/conf ~/logs ~/data ~/source
# 镜像的初始化
我的应用是基于 Python 的,使用 Flask 框架,数据库是 MySQL,然后有用到 Redis 做微信 `Access Token` 的持久化,所以需要先安装 MySQL 和 Redis,最后有用到 Nginx 做代理,这里直接使用的是官方最新镜像
```bash
docker pull mysql
docker pull nginx
docker pull redis
```
因为有用到加速器,所以速度还是杠杠的。
## MySQL
然后是分别将镜像跑起来,为了更灵活的使用,我将 MySQl 的配置文件和数据文件通过 volume 挂载到了宿主机上,这样就算容器挂了,数据还是在的。
下面是 MySQL 的相关配置
```bash
docker run -d --restart=always \
-v /home/docker/data/docker-mysql:/var/lib/mysql \
-v /home/docker/conf/mysql:/etc/mysql/conf.d:ro \
--name mysql \
mysql
```
上述将 MySQL 的数据文件挂载到了宿主机的 `/home/docker/data/docker-mysql` 上,并且将 MySQL 的配置文件也挂载到了宿主机上,然后在 `/home/docker/conf/mysql` 里有设置 MySQL 的默认编码为 `utf8` 的配置文件 `charset.cnf`,具体内容如下
```ini
[client]
default-character-set = utf8
[mysqld]
character-set-server = utf8
[mysql]
default-character-set = utf8
```
## Redis
Redis 的话,因为只是在内存中持久化,所以对数据的保存没有啥要求,对默认配置也没用做修改,所以直接用 Docker 跑起来就可以了
```bash
docker run -d --restart=always \
--name redis \
redis
```
## Web Application
由于用的是 Docker 提供的 `link` 连接容器的,所以在 Nginx 跑起来之前,还需要 Web 先运行起来。
因为用到了 Docker,这一天然的环境隔离神奇,所以对于 Python 之类的各种库依赖来说,直接一个 Docker 镜像打好,然后就随处都可以正常运行了。我没有将我的镜像放到 Docker Hub 或者其他 Registry 上,而是直接写好 Dockerfile,然后上传到服务器上做镜像。下面是我的 Dockerfile
FROM python:2
ADD . /code
WORKDIR /code
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
CMD gunicorn -c gunicorn.conf wsgi:app
我的 Web 程序是基于 Flask 的,然后用 gunicorn 使之运行起来,所以我将 gunicorn.conf
也是放在宿主机上,然后通过 volume 挂载到容器内部的。
docker run -d --restart=always \
-e MODE=PRODUCTION \
--name app_name
-v /home/docker/conf/app_name/gunicorn.conf:/code/gunicorn.conf:ro \
-v /home/docker/conf/focus/production.py:/code/config/production.py:ro \
-v /home/docker/logs/focus/gunicorn:/var/log/gunicorn \
--link redis:redis \
--link mysql:mysql \
app_name:tag
其中 /var/log/gunicorn
里有 gunicorn 里写的日志文件,所以也挂载到了宿主机上。然后我的 Web 程序里的配置文件是通过读取环境变量 MODE
来判断是用开发的配置还是正式的配置,其中用到了 Flask 的配置加载,关键代码如下
def load_config():
"""加载配置类"""
mode = os.environ.get('MODE')
logger = logging.getLogger("app")
try:
if mode == 'PRODUCTION':
from .production import ProductionConfig
enable_pretty_logging({"logging": "info"})
logger.info(b'load from production')
return ProductionConfig
else:
from .development import DevelopmentConfig
enable_pretty_logging()
logger.info(b'load from development')
return DevelopmentConfig
except ImportError, e:
logger.error(e)
sys.exit(1)
对于容器间的访问,我用的是 Docker 提供的 link
,所以通过 docker run
提供的 --link
参数,可以让运行的容器通过一个别名访问另一个容器里的网络,其实是 Docker 写入了容器里的 /etc/hosts
文件里。
其实 Docker 有提供 Docker Compose 来管理应用,但是我选择了直接使用 docker run
,因为我将 docker run
写到了一个脚本里,所以就不想使用 Docker Compose 来增加更多的东西了。