docker -- Docker持久化、数据共享、compose多容器部署

一、了解docker持久化

在这里插入图片描述

1. docker持久化的方案

  • 基于本地文件系统的volum。 可以在执行docker create 或者 docker run时,通过-v参数将主机的目录作为容器的数据卷。这部分功能便是基于本地的文件系统的volume管理
  • 基于plugin的volume, 支持第三方的存储方案,比如NAS,aws
    在这里插入图片描述

  • Volume的类型:
    • 收管理的data volume,有docker后台自动创建
    • 绑定挂载的volume,具体挂载位置有用户指定

2. 数据持久化之 data volume

在这里插入图片描述

  • 参考地址:https://github.com/docker-library/mysql/tree/master/5.7# ‘官方提供的MySQL Dockerfile’
  • data volume 持久化的数据不会随着 容器的删除 而 删除,解决了数据安全的问题
  • 默认产生的data volume的名称偶读非常长,不便于使用,使用-v参数可以指定名称
    示例:-v <volume名称>:<挂载路径>
# 运行一个允许空密码登入的mysql
[root@localhost ~]# docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD mysql

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
36a16497b015   mysql     "docker-entrypoint.s…"   14 seconds ago   Exited (1) 12 seconds ago             mysql1
# 没有启动成功,查看mysql1日志,发现还有密码问题导致无法启动
[root@localhost ~]# docker logs mysql1
2021-05-29 16:55:46+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.25-1debian10 started.
2021-05-29 16:55:46+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2021-05-29 16:55:46+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.25-1debian10 started.
2021-05-29 16:55:46+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of the following:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD
# 删掉之前的mysql
[root@localhost ~]# docker rm mysql1

# 虽然容器被删除了,但是volume依旧在,可以执行 docker volume rm 删除
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     dc21763599f6430ea2a8decee10495c51510fc562f108ec22496cc07c4f91023
[root@localhost ~]# docker volume  rm dc21763599f6430ea2a8decee10495c51510fc562f108ec22496cc07c4f91023
dc21763599f6430ea2a8decee10495c51510fc562f108ec22496cc07c4f91023
# 设置允许空密码
[root@localhost ~]# docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

# 容器up了
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                 NAMES
604a6a4136f0   mysql     "docker-entrypoint.s…"   4 seconds ago   Up 3 seconds   3306/tcp, 33060/tcp   mysql1

# 查看本地volume
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     cffb1dc331784981ef76baa7929a38b50a4407c6c6bc160a1b60e48f6263e4a8

# 查看这个volume的详细信息
[root@localhost ~]# docker volume inspect  cffb1dc331784981ef76baa7929a38b50a4407c6c6bc160a1b60e48f6263e4a8
[
    {
        "CreatedAt": "2021-05-30T01:03:53+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/cffb1dc331784981ef76baa7929a38b50a4407c6c6bc160a1b60e48f6263e4a8/_data",
        "Name": "cffb1dc331784981ef76baa7929a38b50a4407c6c6bc160a1b60e48f6263e4a8",
        "Options": null,
        "Scope": "local"
    }
]

# 利用-v 指定volume的名称和路径
[root@localhost ~]# docker run -d --name mysql2 -v mysql-data:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

# 生成了一个mysql-data的volume
[root@localhost ~]# docker volume  ls
DRIVER    VOLUME NAME
local     cffb1dc331784981ef76baa7929a38b50a4407c6c6bc160a1b60e48f6263e4a8
local     mysql-data

# 查看mysql-data信息,可以看到挂载路径
[root@localhost ~]# docker volume inspect  mysql-data 
[
    {
        "CreatedAt": "2021-05-30T01:13:50+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mysql-data/_data",
        "Name": "mysql-data",
        "Options": null,
        "Scope": "local"
    }
]

验证volume是否有效

# 进入mysql2查看数据库
[root@localhost ~]# docker exec -it mysql2 bash -c mysql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

# 创建docker库
mysql> create database docker;
Query OK, 1 row affected (0.01 sec)

# 强制删除所有的mysql容器
[root@localhost ~]# docker rm -f $(docker ps -aq)

# 查看容器,已经被删除了
[root@localhost ~]#  docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

# 查看volume,mysql-data的数据卷还在
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     mysql-data

# 使用-v指定volume名称和路径(注意,一定要和上面的一致,否则会重新创建一个volume),重新创建一个mysql容器,
[root@localhost ~]# docker run -d --name mysql1 -v mysql-data:/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql

# 进入数据库查看,之前创建docker库还在
[root@localhost ~]# docker exec -it mysql1 bash -c mysql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| docker             |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

3. 数据持久化之 bind mounting

  • bind mount和data volume的区别:
    • data volume:需要在Dockerfile 中定义创建的volume
    • bind mount:只需要在运行容器时-v指定本地路径和容器内路径
      -v <指定本地路径>:<容器内路径>

制作一个nginx访问百度的容器

# 用Dockerfile生成镜像
[root@localhost nginx]# cat Dockerfile 
FROM nginx:latest
WORKDIR /usr/share/nginx/html
COPY index.html index.html

# 利用百度首页生成index.html文件
[root@localhost nginx]# curl www.baidu.com > index.html

# 制作镜像
[root@localhost nginx]# docker build -t test/baidu-nginx .

# 运行容器
[root@localhost nginx]# docker run -d -p 80:80 --name nginx-web test/baidu-nginx

[root@localhost nginx]# docker ps -a
CONTAINER ID   IMAGE              COMMAND                  CREATED         STATUS         PORTS                               NAMES
7f70c92f40c3   test/baidu-nginx   "/docker-entrypoint.…"   9 seconds ago   Up 8 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   nginx-web

访问测试
在这里插入图片描述
使用bind volume

[root@localhost nginx]# ls
Dockerfile  index.html
# 将当前目录映射到容器的/usr/share/nginx/html目录下
[root@localhost nginx]# docker run -d -p 80:80 -v $(pwd):/usr/share/nginx/html --name nginx-web test/baidu-nginx

# 在当前目录下生成一个test.html文件
[root@localhost nginx]# vim test.html 
<head>
<meta charset="utf-8">
<title>YY</title>
<h1>精美壁纸</h1><br>
<img src="http://pic1.cxtuku.com/00/03/34/b3846967c5ac.jpg" />
</head>

访问测试,可以访问新增的test.html文件
在这里插入图片描述

4. bind mounting 实用演示

# 下载代码
[root@localhost ~]# git clone https://github.com/LTP7534/skeleton.git

[root@localhost ~]# cd skeleton

[root@localhost skeleton]# docker build -t test/flask-skeleton .

[root@localhost skeleton]# [root@localhost skeleton]# docker run -d -p 80:5000 -v $(pwd):/skeleton --name flask-skeleton test/flask-skeleton:latest

[root@localhost skeleton]# docker ps -a
CONTAINER ID   IMAGE                  COMMAND            CREATED         STATUS         PORTS                                   NAMES
30b1f87f4cbc   test/skeleton:latest   "scripts/dev.sh"   6 seconds ago   Up 5 seconds   0.0.0.0:80->5000/tcp, :::80->5000/tcp   flask-skeleton

在这里插入图片描述

二、了解docker compose

1. 部署 wordprocess(练习)

  • 参考地址:http://hub.docker.com/_/wordpress
  • 通过多个容器部署wordpress应用

1.1 创建mysql数据库容器

[root@localhost skeleton]# docker run -d --name mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql

[root@localhost skeleton]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                 NAMES
7fc6b75c1989   mysql     "docker-entrypoint.s…"   4 seconds ago   Up 3 seconds   3306/tcp, 33060/tcp   mysql
[root@localhost skeleton]# 

1.2 部署wordpress容器

[root@localhost skeleton]# docker run -d --name wordpress -e WORDPRESS_DB_HOST=mysql:3306 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=123456 --link mysql -p 8080:80 wordpress


[root@localhost skeleton]# docker ps -a
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                   NAMES
275a8f58ff01   wordpress   "docker-entrypoint.s…"   9 seconds ago   Up 7 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   distracted_zhukovsky
7fc6b75c1989   mysql       "docker-entrypoint.s…"   4 minutes ago   Up 4 minutes   3306/tcp, 33060/tcp                     mysql

1.3 浏览器访问

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. docker compose 部署应用

参考地址:https://docs.docker.com/compose/compose-file/compose-file-v3/

  • docker compose 解决了多容器部署管理的问题
  • docker compose是一个工具
  • 这个工具通过一个yml文件定义多容器的docker应用
  • 通过一条命令就可以根据yml文件的定义去创建或者管理多个容器
    在这里插入图片描述
    docker compose 的三大概念
    • Services :

      • 一个Services代表一个container,这个container可以通过Dockerfile创建的image 或者dockerhub上拉取的image创建而来

      • Service的启动类似docker run,我们可以service指定network 和 volume

      • 例如:

        # 示例1:
        services:
         db:
           image: postgres:9.4     # 从dockerhub上拉取的镜像
           volumes:
             - "db-data":/var/lib/postgres/data
           networks:
             - back-tier 
        

        相当于:

        docker run -d --networ kback-tier -v db-data:/var/lib/postgres/data postgres:9.4


        # 示例2:
        services:
         worker:
           build: ./worker     # 利用Dockerfile创建的镜像
           link:
             - db
             - redis
           networks:
             - back-tier 
        
    • Networks :

      • 例如

        在这里插入图片描述

    • Volumes:

      • 例如:

        在这里插入图片描述

2.1 安装 docker compose

[root@localhost ~]# sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

[root@localhost ~]# chmod +x /usr/local/bin/docker-compose

[root@localhost ~]# docker-compose --version
docker-compose version 1.29.2, build 5becea4c


2.2 利用docker compose部署wordpress

  • docker-compose -f <yml文件> up---- 开始编排容器,并且直接运行容器
[root@localhost nginx]# vim docker-compose.yml
version: '3'

services:
  wordpress:
    image: wordpress
    ports:
      - 8080:80
    depends_on:
      - mysql
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: 123456
      WORDPRESS_DB_USER: root
    networks:
      - my-bridge

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-bridge

volumes:
  mysql-data:

networks:
  my-bridge:
    driver: bridge
# 查看yml文件
[root@localhost nginx]# ls
docker-compose.yml

# 开始编排,-f 默认的文件名就是docker-compose.yml,因此这里可以省略指定文件名
# -d参数:后台运行(加上这个参数后,debug日志就不会打印出)
# 一般用于调试时会直接up,不加-d,可以实时查看log
[root@localhost nginx]# docker-compose up&


# 打印出 docker-compose 启动的容器
[root@localhost nginx]# docker-compose ps
      Name                     Command               State                  Ports                
-------------------------------------------------------------------------------------------------
nginx_mysql_1       docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp                 
nginx_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8080->80/tcp,:::8080->80/tcp

访问测试
在这里插入图片描述

# docker-compose stop 可以停止docker-compose启动的容器(不会删除)
[root@localhost nginx]# docker-compose stop

# 查看容器状态
[root@localhost nginx]# docker-compose ps
      Name                     Command               State    Ports
-------------------------------------------------------------------
nginx_mysql_1       docker-entrypoint.sh mysqld      Exit 0        
nginx_wordpress_1   docker-entrypoint.sh apach ...   Exit 0      

# docker-compose start 会将停止的容器再开启
[root@localhost nginx]# docker-compose start 
Starting mysql     ... done
Starting wordpress ... done


# 又会处于运行状态
[root@localhost nginx]# docker-compose ps
      Name                     Command               State                  Ports                
-------------------------------------------------------------------------------------------------
nginx_mysql_1       docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp                 
nginx_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8080->80/tcp,:::8080->80/tcp


# docker-compose down 会将相关的容器,镜像,数据卷等删除
[root@localhost nginx]# docker-compose down
Stopping nginx_wordpress_1 ... done
Stopping nginx_mysql_1     ... done
Removing nginx_wordpress_1 ... done
Removing nginx_mysql_1     ... done
Removing network nginx_my-bridge

# 编排的容器以及被删除
[root@localhost nginx]# docker-compose ps
Name   Command   State   Ports
------------------------------

# -d参数:后台运行(加上这个参数后,debug日志就不会打印出)
[root@localhost nginx]# docker-compose up -d
Creating network "nginx_my-bridge" with driver "bridge"
Creating nginx_mysql_1 ... done
Creating nginx_wordpress_1 ... done


# 查看docker-compose生成的镜像
[root@localhost nginx]# docker-compose images
    Container       Repository    Tag       Image Id       Size  
-----------------------------------------------------------------
nginx_mysql_1       mysql        5.7      2c9028880e58   447 MB  
nginx_wordpress_1   wordpress    latest   0adda6ed742f   550.5 MB

# 进入容器docker-compose exec <yml中定义的Services> bash
[root@localhost nginx]# docker-compose exec mysql bash
root@0539d45f62c3:/# mysql -u root -p123456
mysql> 

# 生成的网络名称格式 : "当前目录名称_yml中定义的networks名称" 如这个nginx_my-bridge
[root@localhost nginx]# docker network ls
NETWORK ID     NAME              DRIVER    SCOPE
5748917a989f   bridge            bridge    local
ef2dd6544dee   host              host      local
6b5d1976ff28   nginx_my-bridge   bridge    local    
0051745c4534   none              null      local
[root@localhost nginx]# docker-compose down
Stopping nginx_wordpress_1 ... done
Stopping nginx_mysql_1     ... done
Removing nginx_wordpress_1 ... done
Removing nginx_mysql_1     ... done
Removing network nginx_my-bridge

3. docker-compose水平扩展和负载均衡

  • 比方说我们有一个web服务,总redis中获取数据,当只有一个web容器时,直接就可以连接访问,但是如果存在多个相同的web,就不能直接访问了,端口会冲突,这时候就需要负载均衡

3.1 实战示例

首先看下web应用程序脚本,会从redis中获取数据,然后web展示

3.1.1 先进行单个web容器的编排部署
[root@localhost flask-redis]# vim 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=5000, debug=True)

查看Dockerfile

[root@localhost flask-redis]# vim Dockerfile 
FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]

查看docker-compose

[root@localhost flask-redis]# vim docker-compose.yml 
version: "3"

services:

  redis:
    image: redis

  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:5000
    environment:
      REDIS_HOST: redis

进行编排,将容器内5000端口映射到8080

[root@localhost flask-redis]# docker-compose up -d

[root@localhost flask-redis]# docker-compose ps
       Name                      Command               State                    Ports                  
-------------------------------------------------------------------------------------------------------
flask-redis_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                                
flask-redis_web_1     python app.py                    Up      0.0.0.0:8080->5000/tcp,:::8080->5000/tcp

访问测试
在这里插入图片描述

3.1.2 多web容器部署
  • 但是在多web容器时,就不能使用上面的yml文件了,会端口冲突,需要借助haproxy
  • 扩容容器命令docker-compose up --scale <service名称>=<扩容数目> -d
  • 这种方式扩展性较强,更加灵活
    在这里插入图片描述
# 先移除之前的
[root@localhost flask-redis]# docker-compose down
Removing flask-redis_redis_1 ... done
Removing flask-redis_web_1   ... done
Removing network flask-redis_default

查看相关文件

[root@localhost flask-redis]# cat 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)


[root@localhost flask-redis]# cat Dockerfile 
FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 80
CMD [ "python", "app.py" ]


[root@localhost flask-redis]# cat docker-compose.yml 
version: "3"
services:

  redis:
    image: redis

  web:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      REDIS_HOST: redis

  lb:
    image: dockercloud/haproxy
    links:
      - web
    ports:
      - 8080:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock 

单容器运行

# 运行容器
[root@localhost flask-redis]# docker-compose up -d

# 访问web
[root@localhost flask-redis]# curl 192.168.10.70:8080
Hello Container World! I have been seen 1 times and my hostname is b04337110d23.

# 查看运行容器
[root@localhost flask-redis]# docker-compose ps -a 
       Name                      Command               State                            Ports                         
----------------------------------------------------------------------------------------------------------------------
flask-redis_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp,:::8080->80/tcp
flask-redis_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                                               
flask-redis_web_1     python app.py                    Up      5000/tcp   

多web容器运行(可以在原基础上直接扩容)

# 这是web容器数量为3
[root@localhost flask-redis]# docker-compose up --scale web=3 -d
flask-redis_redis_1 is up-to-date
Creating flask-redis_web_2 ... done
Creating flask-redis_web_3 ... done
flask-redis_lb_1 is up-to-date

# 查看容器,多出了web_2 和 web_3
[root@localhost flask-redis]# docker-compose ps -a 
       Name                      Command               State                            Ports                         
----------------------------------------------------------------------------------------------------------------------
flask-redis_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp,:::8080->80/tcp
flask-redis_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                                               
flask-redis_web_1     python app.py                    Up      5000/tcp                                               
flask-redis_web_2     python app.py                    Up      5000/tcp                                               
flask-redis_web_3     python app.py                    Up      5000/tcp  

# 访问测试,正常
[root@localhost flask-redis]# curl 192.168.10.70:8080
Hello Container World! I have been seen 2 times and my hostname is b04337110d23.
 

4. 利用docker-compose部署比较复杂的应用

  • voting app:用于投票
  • results app:用于查看投票结果
    在这里插入图片描述

# 下载代码
[root@localhost voting]# git clone https://github.com/LTP7534/voting.git

# 查看docker-compose.yml
[root@localhost voting]# cat docker-compose.yml 
version: "3"

services:
  voting-app:
    build: ./voting-app/.
    volumes:
     - ./voting-app:/app
    ports:
    # 容器的80端口映射到本地的5000端口
      - "5000:80"
    links:
      - redis
    networks:
      - front-tier
      - back-tier

  result-app:
    build: ./result-app/.
    volumes:
      - ./result-app:/app
    ports:
      - "5001:80"
    links:
      - db
    networks:
      - front-tier
      - back-tier

  worker:
    build: ./worker
    links:
      - db
      - redis
    networks:
      - back-tier

  redis:
    image: redis
    ports: ["6379"]
    networks:
      - back-tier

  db:
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
    networks:
      - back-tier

volumes:
  db-data:
  
networks:
  # front-tier 和 back-tier 都没有指明driver,默认时bridge
  front-tier:
  back-tier:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值