当前位置: 首页 > news >正文

Docker 进阶指南(下)- 使用Docker Compose编排多个容器

前言

大家好,我是洋子。在文章《Docker 进阶指南(上)- 使用Dockerfile自定义镜像》介绍了使用DockerFile文件自定义Docker镜像方法,编写好DockerFile文件后,执行docker build命令,即可生成一个镜像,我们再使用docker run命令,即可运行该镜像所生成的容器

但我们使用DockerFile自定义的都是单个镜像,然后手动执行docker run运行单个容器,在实际工作当中,我们需要同时使用到多个容器(如Mysql容器,Nginx容器等),去部署完整的Web服务,那要是想同时部署多个Docker 容器该怎么办呢

这时候需要用到Docker-Compose容器编排工具即可解决这个问题

Docker-Compose 使用方法

Compose 是用于定义和运行多容器 Docker 应用程序的工具

在Docker官网上,提供了使用Docker-Compose的详细例子,https://docs.docker.com/compose/gettingstarted/,下面根据这个例子来操作一遍,部署Python Web开发项目

  1. 安装下载。在已经安装好Docker环境后(Docker的安装方法,可以查看文章Docker快速入门指南),执行以下命令安装Docker-Compose
# 官方下载源,安装慢
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker- compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 其他下载源,安装快
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

安装完毕后,使用docker-compose version验证安装结果,出现以下信息代表安装成功

[root@yangzi ~]# docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019
  1. 创建并进入项目目录
mkdir composetest
cd composetest
  1. 在项目目录下,创建程序入口app.py
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
  1. 创建requirements.txt,此文件存放项目当中需要拉取的依赖包
flask
redis
  1. 创建Dockerfile文件,用于定义Python环境的镜像
# syntax=docker/dockerfile:1
# 基础镜像基于Python3.7
FROM python:3.7-alpine
# 设置工作目录为`/code`
WORKDIR /code
# 设置两个环境变量,启动Flask项目时会读取
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
# 安装gcc等其他依赖
RUN apk add --no-cache gcc musl-dev linux-headers
# 拷贝requirements.txt到工作目录,并且安装python依赖
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# 容器暴露端口5000
EXPOSE 5000
# 把当前项目目录里的内容,拷贝到容器里的工作目录/code
COPY . .
# 容器启动时,执行命令flask run
CMD ["flask", "run"]
  1. 在项目目录下创建 Compose 文件,名字为docker-compose.yml,该文件格式为yaml
version: "3"
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"

这里先简单介绍一下 Compose 文件的格式含义

  • version表示指明Compose文件版本,可以是2.x或者3.x
  • services表示定义了两个服务,用于容器创建,第一个服务名为web,这里使用build关键字,后面还有一个.表示当前目录,它的含义和命令docker build一样,即编译当前目录下的Dockerfile文件创建镜像,同时映射端口8000对应于容器里面的5000端口
  • 第二个服务名为redis,直接使用了官方镜像redis:alpine
  • Compose 文件当中更多字段含义,可以查看官方文档
    https://docs.docker.com/compose/compose-file/
  1. 执行命令docker-compose up -d就可以同时创建两个容器(docker ps 命令可以查看创建的容器),-d参数表示后台执行
[root@yangzi composetest]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS         PORTS                                       NAMES
a84114348ef8   composetest_web   "flask run"              24 minutes ago   Up 9 minutes   0.0.0.0:8000->5000/tcp, :::8000->5000/tcp   composetest_web_1
255dea45b4d6   redis:alpine      "docker-entrypoint.s…"   24 minutes ago   Up 9 minutes   6379/tcp                                    composetest_redis_1

最后用curl http://127.0.0.1:8000命令,验证一下服务的运行情况,也可以用hostname -i 查看到本机的ip,用本地ip:8000端口,在浏览器访问查看效果

[root@zhouyueyang composetest]# curl http://127.0.0.1:8000
Hello World! I have been seen 1 times.

在这里插入图片描述

  1. 如果我们的项目代码,要进行多次修改,按照目前Compose文件的定义,我们需要重新创建容器,可以继续优化一下Compose文件,进行持久化绑定,如我们使用到volumes字段,将本地当前的目录绑定到容器里面的/code目录,在本地目录下修改代码后会实时同步,就不再需要重新创建容器了
version: "3"
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_DEBUG: True
  redis:
    image: "redis:alpine"

Docker 容器数据卷

我们现在已经知道Docker将应用和运行的环境打包形成容器运行,所以容器内产生的数据,都在容器内保存,如果我使用了MySQL容器,不小心把容器删了,所有数据就没有了,这不就直接删库跑路了

那如何将容器内的数据同步到本地,进行持久化存储呢?使用数据卷技术即可解决这个问题

在docker中,卷的本质是文件或者目录,存在一个或者多个容器中,由docker挂载到容器,不属于联合文件系统;对数据卷的修改会立马生效,对数据卷的更新不会影响镜像

数据卷用于容器的持久化,以及容器间的继承和数据共享

容器卷有哪些特点

  • 数据卷可在容器之间共享或重用数据

  • 数据卷中的更改不会包含在镜像的更新中

  • 卷中的更改可以直接生效

  • 数据卷的生命周期一直持续到没有容器使用它为止

如何使用数据卷

  1. 方法一,通过命令行添加,以运行centos容器为例子
#前提条件,先拉取centos7镜像
docker pull centos:7

# 命令
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名
# 测试
[root@yangzi ~]# docker run -it -v /home/test:/home centos /bin/bash

查看数据卷是否挂载成功 docker inspect 容器id,可以看到这里Source就是挂载的宿主机本地的目录在这里插入图片描述
接下来我们在centos容器/home目录进行新建文件,在本地宿主机上/home/test目录就可以出现,同理,在本地卷目录/home/test下更新文件,centos容器里面相应目录下,也会进行内容更新

下面的操作就是在宿主机挂载的卷目录下新建了xxx.java文件,自动同步到容器里面

[root@yangzi test]# touch xxx.java
[root@yangzi test]# ls
xxx.java
[root@yangzi test]# docker attach 531a8f70f60c
[root@531a8f70f60c /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@531a8f70f60c /]# cd /home
[root@531a8f70f60c home]# ls
xxx.java
  1. 其余使用方法。在DockerfileCompose文件当中同样可以使用到数据卷,只是定义的语法上略有不同,在之前文章《Docker 进阶指南(上)- 使用Dockerfile自定义镜像》,以及本篇文章均有相关介绍,这里就不再重复讲解了

docker的常用命令大总结

  • 操作容器的常用命令有 docker psdocker rundocker execdocker stop
  • 操作镜像的常用命令有 docker imagesdocker rmidocker tagdocker build
  • 操作镜像仓库的常用命令有 docker pulldocker push

如果前面的内容都已经学完了,看这张图就比较容易了,Docker命令都是基于Registry镜像仓库和Images镜像,Container容器这三个角色展开,其中的大部分命令我们都使用过了
在这里插入图片描述

结束语

到这里,Docker的系列的三篇文章就完结了,后面即将开启学习新的容器技术k8s,毕竟这才是目前容器技术的主角

如果你觉得本篇文章对你有帮助,麻烦点一下【赞】和【在看】,你的支持就是我前进的动力

相关文章:

  • 走进Prime Time系列 - 走进PT - 01
  • 天龙八部科举答题问题和答案(全4/8)
  • 【聚类算法】带你轻松搞懂K-means聚类(含代码以及详细解释)
  • 【电源专题】案例:为什么芯片支持0.8V的工作电压,但EN却又要高达1.25V?
  • 湖仓一体电商项目(十四):实时任务执行流程
  • 猿创征文|Java中的IO流大家族 (两万字详解)
  • SQL Server 2014安装教程(保姆级图解教程)
  • 大白话理解-微信小程序获取授权
  • Spring常用注解。
  • Spring之拦截器
  • 【知识图谱】Louvain、LPA等5类经典社区发现算法 Python 实战
  • SQL server 2008 r2 安装教程
  • python wechat --- 企业微信机器人API
  • 阿里云ossutil使用
  • Spring——事务注解@Transactional【建议收藏】
  • [deviceone开发]-do_Webview的基本示例
  • avalon2.2的VM生成过程
  • Golang-长连接-状态推送
  • Java基本数据类型之Number
  • Lsb图片隐写
  • Node + FFmpeg 实现Canvas动画导出视频
  • oschina
  • Python打包系统简单入门
  • Python学习之路16-使用API
  • rabbitmq延迟消息示例
  • 创建一种深思熟虑的文化
  • 搞机器学习要哪些技能
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 微信公众号开发小记——5.python微信红包
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • Spring Batch JSON 支持
  • 数据库巡检项
  • ![CDATA[ ]] 是什么东东
  • #if 1...#endif
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (2)STM32单片机上位机
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (70min)字节暑假实习二面(已挂)
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C语言)字符分类函数
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (四)鸿鹄云架构一服务注册中心
  • (一)RocketMQ初步认识
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • (轉)JSON.stringify 语法实例讲解
  • .htaccess 强制https 单独排除某个目录
  • .Net - 类的介绍
  • .net core 6 集成和使用 mongodb
  • .Net FrameWork总结
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 药厂业务系统 CPU爆高分析
  • .net6Api后台+uniapp导出Excel
  • .NET关于 跳过SSL中遇到的问题
  • .ui文件相关
  • ??myeclipse+tomcat