手动部署 wordpress
# 部署 mysql
docker run -d --name mysql -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql:5.7
# 部署 wordpress
docker run -d -e WORDPRESS_DB_HOST=mysql --link mysql -p 8080:80 wordpress
注意:如果平时最新版本的 Mysql,执行以上操作部署完成之后,访问 WordPress 站点会出现 ,Error establishing a database connection,显然,数据库连接失败。通过访问 mysql 容器的 log 来排查问题。
docker logs mysql
#提示:The server requested authentication method unknown to the client
#认证方法错误,mysql8.0 以后默认的认证方式改了,所以才会有这样的错误
# 解决办法
#进入mysql容器
docker exec -it mysql /bin/bash
#登陆数据库
mysql -u root -p
use mysql;
#开启root远程访问权限
grant all on *.* to 'root'@'%';
#修改加密规则
alter user 'root'@'localhost' identified by 'root' password expire never;
#更新密码
alter user 'root'@'%' identified with mysql_native_password by 'root';
#刷新权限
flush privileges;
通过手动部署 WordPress 可以发现,手动部署一个多容器应用非常不方便,至少需要经过以下几个步骤:
- 从 Dockerfile build image 或者 Docker Hub 拉取 image
- 创建多个 container
- 管理这些 container(启动、停止、删除)
所以我们需要使用 Docker Compose 去部署和管理多容器应用。
Docker Compose
基本概念
Docker Compose 是 docker 官方编排工具 ,可以通过一个模板(YAML格式)定义多容器的 docker 应用,通过一条命令就可以根据模板创建和管理多个容器。
Docker Compose 目前有三个版本,推荐使用 Version 3,因为Version 3 可以用于多机部署。
注意:Mac、Window10 环境下安装 docker 时同时安装了 docker compose,linux 环境下需要手动安装。
模板文件的组成:
service
- 一个 service 代表一个 container ,这个 container 可以从 dockerhub 的 image 来创建,或者从本地 Dockerfile 文件 build 出来的 image 创建。
- service 的启动类似 docker run,我们可以给它指定 network 和 volume
```yaml
从 dockerhub 的 image 来创建
services: db:image:mysql
volumes:
- mysql:/var/lib/mysql
从本地 Dockerfile 文件创建
services: node-http: build: context: . # 指定 Dockerfile 文件所在的目录 dockerfile: Dockerfile links: # 连接到同一个自定义 network 的容器默认是互相连接的,可以不配置 links
- mysql
**volume**
```yaml
# 指定数据卷
volumes:
db-data:
# 等同于
docker volume create db-data
network
# 指定自定义网络
networks:
my-bridge:
driver: bridge
# 等同于
docker network create -d bridge my-bridge
部署 wordpress 的 模板文件
# 使用默认的自定义网络
# 默认情况下会自动创建一个自定义网络,并且容器默认都连接到这个自定义网络
version: '3'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql:/var/lib/mysql
volumes:
mysql:
# 使用 networks 关键字指定自定义网络
version: '3'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_PASSWORD: root
networks:
- my-bridge
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress
volumes:
- mysql:/var/lib/mysql
networks:
- my-bridge
volumes:
mysql:
networks:
my-bridge:
driver: bridge
基本命令
# 创建容器
docker-compose build
# 创建并启动容器
docker-compose up -d # -d 参数指定在后台启动容器
# 启动容器
docker-compose start
# 停止容器
docker-compose stop
# 停止并删除容器和对应的自定义网络
docker-compose down
# 查看对应的镜像和容器
docker-compose images
# 查看对应容器
docker-compose ps
# 进入指定的容器
docker-compose exec xxx # naem为 service 中定义的名称 docker-compose exec mysql bash
# 查看容器运行日志
docker-compose logs
水平扩展和负载均衡
通过 Docker Compose 的 —scale 命令可以同时部署多个web应用供用户访问,并结合负载均衡器实现负载均衡,提高服务的稳定性。
测试:通过 docker-compose --scale
命令部署多个 Web 服务,通过 HAproxy 转发到不同的服务
# app.py
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
# Dockerfile
FROM python:2.7
LABEL maintaner="gongyz 1018017334"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 80
CMD [ "python", "app.py" ]
# docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
# 使用 --scale 不要再指定宿主机端口,因为宿主机只有一个 8080 端口
#ports:
# - 8080:80
environment:
REDIS_HOST: redis
lb:
image: dockercloud/haproxy
links:
- web
ports:
- 8080:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
启动容器
# 构建镜像
docker-compose build
# 部署镜像
docker-compose up --scale web=4 -d