Docker

1. 容器技术

容器 用于代码和依赖资源打包

同一台主机可运行多个容器 共享操作系统内核 同时各自作为独立进程运行

相较于虚拟机 容器占用空间小 启动速度块


1.1 VM虚拟机 &&Docker

VM虚拟机 通过模拟硬件 并在硬件上安装操作系统实现虚拟化应用

Docker最优虚拟程序所需的环境配置



特性

Docker

VM

启动速度

秒级

分钟级

硬盘使用

MB

GB

性能

接近原生

弱于

系统支持量

单机支持上千个容器

通常几十个


1.2 Docker容器技术多用于搭建和配置开发环境



2. Docker (C/S架构)

2.1 Docker安装

# Windows10 Docker-CE社区版 安装
    # 在控制面板-程序与功能-开启Hyper-V
    # 安装Docker-Desktop url:https://www.docker.com/products/docker-desktop
    # 适用于Windows10 专业版或企业版(部分版本 版本号尽量最新)
    
# Linux(Ubuntu) 安装
sudo apt-get update
sudo apt-get install docker-ce

# 启动docker服务
sudo systemctl enable docker
sudo systemctl start docker


2.2 Docker-images(镜像)

# Docker镜像是特殊的文件系统 提供容器运行所需的程序 库 资源配置文件 还包含运行时的配置参数(环境变量 用户 挂载等等) 分层构建且每层都是只读

# 修改镜像加速源 提高下载速度
-----------ubutun /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://dockerhub.azk8s.cn",
    "https://hub-mirror.c.163.com"
  ]
}
-------------------------------------------

# 修改默认的镜像下载目录
-----------ubutun /etc/docker/daemon.json
{
  "graph":"自定义的镜像下载目录",
}

# 配置文件参数问题 根据docker版本号查看指定的daemon.json配置文件参数设置
# https://docs.docker.com/engine/reference/commandline/dockerd/

# 重启服务
sudo systemctl daemon-reload
sudo systemctl restart docker

# 查看是否生效Registry-Mirros
docker info


# Docker-images常用命令

# 查看镜像
docker images  | docker image ls  # 所有顶层镜像
docker image ls -a # 所有 中间层镜像 + 顶层镜像 -q:显示镜像id
docker images 镜像  # 查看指定镜像
docker history 镜像id  # 查看指定镜像创建历史记录
docker inspect 镜像id  # 查看镜像具体信息(id, 执行命令, 环境变量, 网络信息,挂载等)

# 搜索镜像
docker search 镜像

# 下载镜像(不写版本默认最新)
docker pull 镜像:版本号

# 标记镜像到指定仓库(重命名)
docker tag [options] image[:tag] [registryhost/][username/] name[:tag]

# 删除镜像
docker rmi -f 镜像id  # -f:强制删除
docker image prune # 删除悬空镜像(因版本更新迭代重名原因成为None标记的镜像)

# 通过源镜像创建的容器构建新镜像(不推荐 分层构建的镜像内容不可见 且容易造成新镜像臃肿)
docker commit [options]  容器id | 容器名  新镜像名称:标签


# 其他操作--镜像持久化(默认tar包) 实现本地 网络共享
# 保存
docker save 镜像id > ./xx.tar | docker save -o ./xx.tar 镜像id

# 加载
docker load -i ./xx.tar

# 这种方式创建的新镜像保留源镜像(通过build)分层创建的历史 可执行理论上回滚操作docker tag 回滚层id 镜像id
# 如若出现新镜像为None情况 请使用镜像名:版本号方式进行


2.3 Docker-container(容器)

#Docker-Container 实质是在镜像的基础上添加一个可写层 用来保存容器运行过程的修改信息
# 通过镜像创建容器
docker run -it --rm -d 镜像:版本号 |镜像id  命令  
# 常用参数:
#-it:终端交互| -rm:退出删除容器| -d:守护进程 后台运行| --name 容器名| -p 主机port:容器port
#-e 环境变量| --link 关联其他容器名| -v 主机目录:容器目录 >实现挂载卷共享数据

# 查看容器
docker ps # 查看运行容器 -a:查看所有容器

# 已有容器操作
docker start 容器id | 容器名  # 运行停止(多个)容器
docker restart 容器id | 容器名  # 重启
docker stop 容器id | 容器名 # 停止

docker inspect 容器id  # 查看容器详细信息
docker exec -it 容器id | 容器名 命令  # 交互界面进入运行中容器进行操作 exit不会导致容器停止
docker attach 容器id | 容器名  # exit会导致容器停止(不推荐)
# docker exec -it xxx bash  shell界面进入xxx容器

# 删除容器(支持多个容器同时删除)
docker rm 容器id | 容器名 # -f:强制删除 -l:只删除容器间网络连接 -v:删除挂载卷+容器

# 容器文件与其他主机文件复制操作
docker cp 源目录 目录
docker cp 源目录 容器:目的目录  || docker cp 容器:目录  目的目录


# 其他操作(通过容器持久化操作实现容器共享)
# 导出容器到指定tar包
# 默认以tar方式对容器进行持久化存储(记录下容器参数-command) docker inspect 容器id 查看详情
docker export 容器id | 容器名  > ./xxx.tar | docker export -o xxx.tar 容器id

# 导入tar包生成新镜像
docker import ./tar文件 新镜像名:版本

# 运行生成的新镜像创建的容器
docker run 新镜像id  command(导出容器)

# 这种方式创建出的新镜像丢失了源镜像内分层构建的详情 同时对于(多层构建build的新镜像)无法执行回滚操作


2.4 Docker-Repository(仓库)

#---------镜像上传到公有仓库docker hub

# 登录账号
docker login  -u username -p password # 登录https://hub.docker.com/ 输入用户账号&密码

# 标记上传的镜像
docker tag 上传的镜像id 用户账号/新镜像名称:版本号

# 上传到docker hub仓库(默认不允许https方式上传镜像)
docker push 用户账号/新镜像名称:版本号


#----------镜像上传到私有仓库docker-registry

# 登录私有仓库
docker login 私有仓库url(ip:port)

# 下载私有仓库镜像
docker pull registry 

# 后台运行 & 同步数据到主机 & 映射ip&端口(访问localhost:6666)
docker run -d --restart=always -v ./registry:/var/lib/registry -p 6666:6666 registry:latest

# 标记上传的镜像
docker tag 镜像id  私有仓库地址(ip:port)/镜像id

# 上传到私有仓库(curl localhost:6666/v2/_catalog查看上传的镜像)
docker push ip:port/新镜像名:版本号

# 下载私有仓库镜像
docker pull localhost:6666/镜像:版本号

# 注意点:局域网内私有仓库搭建需要配置docker settings信息
------------json-----------/etc/docker/daemon.json
{
"insecure-registries":["局域网ip:port", 192.xxx.xxx.xxx:6666]
}
------------------------------------------------



3. Dockerfile可视化制作镜像

3.1 Dockerfile常用指令

# Dockerfile脚本文件自定义镜像(单个)

# Dockerfile常用指令
#-----------Dockerfile
# 基础镜像
FROM 指定基础镜像 # 指定基础镜像

# 维护者信息
MAINTAINER username | email

# 构建镜像执行指令
ENV key value |key=value # 指定环境变量

WORKDIR 目录路径  # 指定工作目录

RUN 执行命令 # 多用于程序安装执行命令

COPY 源路径 目标路径  # 复制文件
ADD 源路径 目标路径 # 复制文件(源路径:文本+URL+tar压缩文件)下载链接文件&&自动解压缩文件

VOLUME /目录  # 指定持久化存储目录

EXPOSE port1, port2  # 映射端口号 docker run -P 自动映射port1, port2;

# 容器启动时执行的指令
CMD shell命令 | ["par1", "par2",...]  # 指定容器主进程需要的参数(容器=进程)
ENTRYPOINT shell命令 | ["par1", "par2"]  # 可对CMD命令进行重定义 容器启动前预处理配置

# 使用Dockerfile构建新镜像
docker build -t 镜像名:版本 上下文路径/URL  # 上下文路径 != 目录 

# 注意点:
# Docker(c/s)架构 上下文路径实则是server对用于构建镜像的资源进行打包的地址
# Dockerfile构建新镜像会对所属目录下所有资源文件进行打包到docker-server 方便其构建使用
# Dockerfile 可指定脚本文件执行并不需要一定在上下文目录中 docker build -t -f 指定的文件名 新镜像 上下文路径
# Dockerfile可添加忽略文件 避免被打包使用 >添加.dockerignore(类比:.gitignore)
# Dockerfile v17版本支持多阶段构建 尽可能减少分层构建带来的镜像资源冗余


3.2 Dockerfile实例

# 简易搭建Django环境

----------requirements.txt
asgiref==3.2.10
Django==3.1.1
django-redis==4.12.1
mysqlclient==2.0.1
pytz==2020.1
redis==3.5.3
sqlparse==0.3.1

-----------Dockerfile
# 指定基础镜像
FROM python:3.7

# 配置Django环境&创建Django项目
COPY requirements.txt /home

WORKDIR /home

RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple \
&& django-admin startproject project


WORKDIR /home/project

EXPOSE 8000

# 设置容器启动后执行的命令
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
----------------------------------------------------------

# 构建镜像
docker build -t django:1.0 .

# 运行容器
docker run -it --name web_django -p:8888:8000 django:1.0


容器tcp_docker



4. Docker-compose

4.1 认识

Docker compose 是用于快速部署分布式应用的一个docker官方编排项目(python实现)
			  为了方便编排管理多个容器而生
			  通过docker-compose.yml文件(YAML格式)来定义一组相关联的容器为一个项目并进行管理
			  
Compose:
	   服务(service):一个应用容器
	   项目(project):由一组关联的应用容器组成的一个完整业务单元 在 docker-compose.yml 文件中定义


4.2 Docker-compose 安装

# Mac or win10 Docker Desktop 自带docker compose
# 查看信息
docker-compose version

# Linux
pip install -U docker-compose


4.3 Docker-compose使用

#Compose模板文件 :docker-compose.yml  YAML语法
version:"3"  # 指定compose版本

services:  # 服务
	app:  # 项目应用
		image: 镜像  # 加载指定镜像指令
		ports:
			- "5555:5555"  # 端口映射
		volumes:
			- "/home"  # 挂载卷

# 服务:
#	应用:
#		指令:


4.4 Docker-compose 常用命令

#Docker-compose常用命令
# 测试语法是否书写正确
docker-compose config

# 构建服务
docker-compose build 应用  

# 查看所有(特定)服务构建日志
docker-compose logs (可选:应用)

# 自动构建镜像 创建服务 启动服务
docker-compose up

# 查看compose项目中包含的镜像
docker-compose images

# 查看compose项目所有容器
docker-compose ps

# 停止所有(特定)应用服务
docker-compose stop (可选:应用)

# 停止并删除docker-compose up启动的服务 删除网络
docker-compose down

# 重启所有(特定)应用服务
docker-compose restart (可选:应用)

# 进入特定启动中的应用服务
docker-compose exec  应用  命令(如:bash)


4.5 Docker-compose 服务常用指令

# Docker-compose常用指令(必须优先声明服务)

1.build: .  # 指定Dockerfile文件上下文路径 构建镜像并使用 
#build:
	context: ./test  # 指定Dockerfile文件路径
	dockerfile: xxx  # 指定Dockerfile文件名
	

2.image: redis  # 加载镜像(本地仓库不存在自动pull)
	
	
3.expose:   # 映射端口(不映射到宿主机)
	- 8000


4.container_name: docker-mysql  # 指定容器名


5.depends_on:   # 优先级启动容器设置
#app1:
	build: .
	depends_on:
		- app2
		
#app2
	images: mysql 
	
	
6.ports:  # 映射端口(映射到宿主机 外部以可访问)
	- "8001:8000"  # (ip:host:container)


7.secrets:存储隐私数据
#mysql:
	image: mysql
	environment:
		MYSQL_ROOT_PASSOWRD_FILE: /run/secrets/mysql_psw 
	secrets:
		- mysql_psw

#secrets:
	db_psw:
		file: ./xxx.txt
		
		
8.volumes:  # 挂载卷路径(宿主机:容器:访问模式[ro])
 - ./mysql:/var/lib/mysql
 
9.command: python manage.py runserver  # 替换容器启动后默认执行的命令(Dockerfile CMD指令)

10.entrypoint: /xx.sh  # 应用服务容器启动后执行的入口文件

11.networks:  # 设置应用服务容器连接网络
	- 自定义网络
	
12.environment:  # 设置应用服务容器运行的环境变量
	par1: 1


4.6 Docker-compose 实例

# 实例:Docker-compose 构建 Django + Mysql + Redis服务

#目录结构
#-->compose
#------->docker-compose.yml
#------->mysql
#------->redis
#------->django
#-------------->requirements.txt
#-------------->Dockerfile
#-------------->project


###---->django/project/project/settings.py
# 宿主机在虚拟环境下创建一个Django工程(django-admin startproject project) 到./django
# Mysql配置(pip install pymysql)
# Django操作Mysql需要Mysqldb驱动程序
# Django版本低 可以使用pymsyql替代(pymysql.install_as_MySQLdb())
# 因为Django版本与Mysqldb驱动关联 所以特别注意 Django3使用(pip install mysqlclient)关联数据库
DATABASES = {
      'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
        'HOST': 'mysql',  # 数据库主机&docker-compose服务名
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': 'python',  # 数据库用户密码
        'NAME': 'test_db'  # 数据库名字
        }
}
# Redis配置(pip install django-redis)
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://redis:6379/0",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}



###---->django/Dockerfile
FROM python:3.7

COPY requirements.txt /home

WORKDIR /home

RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple \
&& django-admin startproject project

WORKDIR /home/project

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]



###---->django/requirements.txt
asgiref==3.2.10
Django==3.1.1
django-redis==4.12.1
mysqlclient==2.0.1
pytz==2020.1
redis==3.5.3
sqlparse==0.3.1



###---->docker-compose.yml
version: "3"
services:
  web:
    build: ./django

    volumes:
      - ./django/project:/home/project

    ports:
      - "8000:8000"

    depends_on:
      - mysql
      - redis


  mysql:
    image: mysql:8.0.1

    expose:
      - 3306

    ports:
      - "3307:3306"

    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: python
      
    volumes:
      - ./mysql:/var/lib/mysql


  redis:
    image: redis

    expose:
      - 6379

    ports:
      - "6380:6379"

    volumes:
      - ./redis:/var/lib/redis


容器tcp_容器tcp_02



5. Docker 网络链接

# 外部访问容器内
# 通过ip:port映射(可多个)
docker run -p  宿主机ip:宿主机端口:容器端口 镜像id  # -P 会映射EXPOSE 端口

# 查看映射端口信息
docker port 容器id 端口号


# 内部多容器通信

# 查看docker默认网络连接类型
docker network ls  # 默认有三种bridge host null

# 查看网络连接方式详情
docker network inspect 网络id

# 创建新的网络连接
docker network create -d 网络连接方式 新网络名 

# 创建容器时指定特定网络连接
docker run --network 新网络名 镜像id


# docker-compose 会创建新的bridge网络连接(文件名+_default) 
# 多个容器间通信亦可使用参数: --link 关联容器