Docker

一、Docker是什么

1. 简介

docker官网docker仓库

Docker 是一个开源的应用容器化技术引擎,基于 Go 语言并遵从 Apache2.0 协议开源。

比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内容,容器没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响1.简介1.简介

2. 基本组成

  1. ![](15Docker.assets/image-20200725080807257.png#crop=0&crop=0&crop=1&crop=1&id=r7YB3&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)

Docker使用了C/S体系架构,Docker客户端(Client )与Docker守护进程(Docker Damon)通信,Docker守护进程负责构建,运行和分发Docker容器。

  • 镜像(Image)**:Docker 镜像(Image),就相当于是一个 root 文件系统。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
  • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

二、Docker安装

1. 服务安装

参考帮助文档:https://docs.docker.com/engine/install/

#1.卸载旧版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#2.需要的安装包
yum install -y yum-utils
#3.设置镜像的仓库,推荐使用国内的
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新yum软件包索引
yum makecache fast
#4.安装docker相关的 docker-ce 社区版 而ee是企业版
yum install docker-ce docker-ce-cli containerd.io
#6. 使用docker version查看是否按照成功
docker version
#7. 测试
docker run hello-world

卸载docker

#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源, /var/lib/docker 是docker的默认工作路径!
rm -rf /var/lib/docker

2. 阿里云镜像加速

阿里云—>产品与服务—>容器镜像服务—>镜像加速器

Docker - 图1

三、Docker常用命令

Docker - 图2

1. 帮助命令

docker version    #显示docker的版本信息。

docker info       #显示docker的系统信息,包括镜像和容器的数量

docker logs          #显示日志

docker 命令 --help #帮助命令

2. 镜像命令

docker images [可选参数]#查看所有本地主机上的镜像 可以使用docker image ls代替
    -a, --all             #列出所有镜像
    -q, --quiet           # 只显示镜像的id

docker search #搜索镜像,可到官网直接查询

docker pull #下载镜像,如果不写tag,默认就是latest

docker rmi [可选参数]#删除镜像,可指定多个
    -f $(docker images -aq) #删除全部的镜像

3. 容器命令

docker run [可选参数] image #新建容器并启动
    --name="Name"        #容器名字 tomcat01 tomcat02 用来区分容器
    -d                    #后台方式运行
    -it                 #使用交互方式运行,进入容器查看内容
    -p                    #指定容器的端口 -p 8080(宿主机):8080(容器),如果是大写则随机指定端口

docker ps #列出当前正在运行的容器
  -a, --all             #所有容器
  -q, --quiet           #只显示ID

exit #容器内执行退出容器,ctrl +P +Q 容器不停止退出

docker rm 容器id   #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
    -f $(docker ps -aq)  #删除所有的容器

docker start 容器id    #启动容器
docker restart 容器id    #重启容器
docker stop 容器id    #停止当前正在运行的容器
docker kill 容器id    #强制停止当前容器

docker top 容器id     # 查看容器中进程信息

docker inspect 容器id     #查看镜像的元数据,如卷挂载信息

docker exec -it 容器id bashshell(/bin/bash) #进入当前容器后开启一个新的终端(常用)
docker attach 容器id                          #进入当前容器正在执行的终端

docker cp 容器id:容器内路径 主机目的路径 #从容器内拷贝到主机上
示例➜  ~ docker exec -it  55321bcae33d /bin/bash 
    ➜ [root@55321bcae33d /]# ls
    ➜ #新建一个文件
    ➜ [root@55321bcae33d /]# echo "hello" > java.java
    ➜ [root@55321bcae33d /]# cat java.java 
    ➜ hello
    ➜ [root@55321bcae33d /]# exit
    ➜ exit
    ➜  ~ docker cp 55321bcae33d:/java.java /    #拷贝
    ➜  ~ cd /              
    ➜  / ls  #可以看见java.java存在

4. 网络命令

docker network
                connect     -- Connect a container to a network
                create      -- Creates a new network with a name specified by the
                disconnect  -- Disconnects a container from a network
                inspect     -- Displays detailed information on a network
                ls          -- Lists all the networks created by the user
                prune       -- Remove all unused networks
                rm          -- Deletes one or more networks

四、Docker镜像详解

1. 镜像是什么

镜像是一种轻量级、可执行的独立软件包(类似APP的安装包),包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。

2. 镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称为UnionFS(联合文件系统,一种分层、轻量级并且高性能的文件系统)。

Docker - 图3

Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!这一层就是我们通常说的容器层,容器之下的都叫镜像层!

Docker - 图4

3. 镜像提交

docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG] #提交容器成为一个新的副本

五、容器数据卷

1. 容器数据卷是什么

Docker容器中产生的数据,同步到宿主机上,使用目录的挂载,将容器内的目录,挂载到Linux。容器的持久化和同步操作,容器间也是可以数据共享的

2. 使用数据卷

(1)直接使用命令挂载 -v

docker run -it 
                -v 容器内路径            #匿名挂载(一般不用,)
                -v 卷名:容器内路径          #具名挂载
                -v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
                                        : ro     #readonly 只读
                                        : rw     #readwrite 可读可写
docker volume ls  # 查看所有的volume的情况,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data

(2)使用docker镜像的构建文件Dockerfile

六、Dockerfile

1. DockerFile介绍

dockerfile是用来构建docker镜像的文件,命令参数脚本。

(1)Vim创建一个dockerfile文件

命名建议使用Dockerfile;格式指令(大写) 参数;指令执行从上到下顺序;每一个指令,对应镜像里的一层

FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash

(2) docker build 构建称为一个镜像

# 2、通过这个文件构建镜像
# 命令 docker build -f 文件路径 -t 镜像名:[tag] .
docker build -f Dockerfile -t mycentos:0.1 .

(3) docker run运行镜像

 docker run mycentos:0.1 .

(4) docker push发布镜像(DockerHub 、阿里云仓库)

2. DockerFile指令

FROM                # 基础镜像,一切从这里开始构建
MAINTAINER            # 镜像是谁写的, 姓名+邮箱
RUN                    # 镜像构建的时候需要运行的命令
ADD                    # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR                # 镜像的工作目录
VOLUME                # 挂载的目录
EXPOSE                # 保留端口配置
CMD                    # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT            # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD                # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。
COPY                # 类似ADD,将我们文件拷贝到镜像中
ENV                    # 构建的时候设置环境变量!

3. 实战示例(Tomcat)

(1)准备镜像文件

准备tomcat 和 jdk到当前目录,编写好README

Docker - 图5

(2)编写dokerfile

FROM centos #选择centos为基础镜像
MAINTAINER cheng<1204598429@qq.com> #作者信息
COPY README /usr/local/README #复制文件
ADD jdk-8u231-linux-x64.tar.gz /usr/local/ #复制解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local/ #复制解压
RUN yum -y install vim
ENV MYPATH /usr/local #设置环境变量
WORKDIR $MYPATH #设置工作目录
ENV JAVA_HOME /usr/local/jdk1.8.0_231 #设置环境变量
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 #设置环境变量
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib #设置环境变量 分隔符是:
EXPOSE 8080 #设置暴露的端口
CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out # 设置默认命令

(3)构建镜像

# 因为dockerfile命名使用默认命名dockerfile 因此不用使用-f 指定文件
docker build -t mytomcat:0.1 .

(4)run镜像

$ docker run -d -p 8080:8080 --name tomcat01 -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.1

4. 发布镜像

可以发布至官网或者阿里云

七、Docker 网络

1. Docker 0

使用 ip addr 查看网络

Docker - 图6

Docker 安装即配置Docker 0,而每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!

2. 容器自定义网络

容器之间相互隔离的,默认使用docker0进行通信,但是使用docker0通信不支持域名访问。示例:docker exec -it tomcat02 ping tomca01 # ping不通,只能ping ip地址, 可以使用--link打通两个容器连接,但是很麻烦,已不推荐使用

Docker - 图7

# 可以自定义一个网络 
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 查看刚定义的网络 
    docker network inspect mynet;
# 运行容器时使用自定义网络
docker run -d -P --name Tomcat01 --net mynet tomcat
docker run -d -P --name Tomcat02 --net mynet tomcat    
# 已有容器使用自定义网络
docker network connect mynet Tomcat01

自定义网络下可以通过名字来进行通信

3. 部署Redis集群

# 创建网卡
docker network create redis --subnet 172.38.0.0/16

# 通过脚本创建六个redis配置
for port in $(seq 1 6);\
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 通过脚本运行六个redis
for port in $(seq 1 6);\
docker run -p 637${port}:6379 -p 1667${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker exec -it redis-1 /bin/sh #redis默认没有bash
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379  --cluster-replicas 1

八、IDEA整合Docker镜像

(1)构建SpringBoot项目

(2)打包运行

mvn package

(3)编写dockerfile

FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]

(4)构建镜像

# 1.复制jar和DockerFIle到服务器
# 2.构建镜像
docker build -t xxxxx:xx  .

(5)发布运行

九、Docker Compose

1. 什么是Docker Compose

之前每个容器都需要单独启动,多个容器启动过于繁琐。

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用docker-compose up命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

2. Docker Compose安装及快速使用

(1)下载

 curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # 官方源慢替换为当前

sudo chmod +x /usr/local/bin/docker-compose # 授权

(2)使用官方示例(6步)

# 1.新建项目文件夹
mkdir composetest
cd composetest

# 2.在项目文件夹里新建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)

# 3.在项目文件夹里新建requirements.txt
flask
redis 

# 4.在项目文件夹里新建Dockerfile 文件
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

# 5.在项目文件夹里新建docker-compose.yml文件
version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

# 6.在项目文件夹里运行docker-compose up  
docker-compose up

3. docker-compose.yml规则

菜鸟文档

# yaml 配置实例,3层结构

version: '3' # 第一层:版本信息向下兼容
services:     # 第二层:服务信息
  web:
    build:    ## 从自己定义的镜像构建容器
       depends_on: 
            -redis  ## 依赖关系,会先启动
  redis:
    image: redis

volumes:    # 第三层:其他配置
  logvolume01: {}

十、Docker Swarm

1. Docker Swarm是什么

在之前我们只是在一台机器来进行docker的管理,是分布式的处于多台主机上,这时就可以借助于Swarm,Swarm是Docker自带的编排工具,只要你安装了Docker就会存在Docker Swarm工具。

Swarm中的模式是有两大类节点,一类是manager节点,另一类是worker节点,manager节点相当于对服务的创建和调度,worker节点主要是运行容器服务,当然manager节点也是可以运行的。

Docker - 图8

2. Docker Swarm集群搭建

(1)创建一个Manager节点-init

docker swarm init --advertise-addr=[本机ip地址] # 服务器1成为一个Manager节点,这样其它的节点都可以知道这个节点的存在,创建成功后会返回一个通知

(2)创建一个worker节点-join

docker swarm join --token SWMTKN-1-0zzpk3xqq2ykb5d5jcd6hqeimckhrg5qu82xs7nw2wwnwyjmzg-9tmof9880m9r92vz5rygaa42e 192.168.0.108:2377 # 将返回的通知写入,让服务器2成为一个worker节点

(3)查看节点状态

docker node ls #只能在manager节点那台机器上查看,普通节点无法执行查看命令

3. Raft一致性协议了解

4. 集群容器创建

docker server create #  docker server create 相当于docker run 就是创建容器,只不过在swarm中是不同的表现方式

docker service ls  #  查看服务内容

docker service ps [服务名]#  查看当前服务内容

docker service scale [服务名]=5 # 服务水平扩展
docker service update [服务名]=5 # 功能同上

十、Docker Stack、Docker Secret

此节点下的使用在实际使用中—help查询不做详细探究

1. Docker Stack

使用方式与compose类似(使用k8s代替)

# 单机
docker-compose up 
# 集群
docker stack deploy

2. Docker Secret

应用