Docker学习笔记

Docker学习笔记

1. Docker入门

1.1 Docker三要素

  1. 镜像:只读模板,可以用来创建Docker容器。一个镜像可以创建多个容器实例。

    Docker镜像类似于Java的类,而Docker容器则类似于Java的对象

  2. 容器:Docker利用容器独立运行一个或一组应用,应用程序或服务运行在容器里面,容器类似于一个虚拟化的运行环境

    容器可以被启动、开始、停止、删除。每个容器都是互相隔离、保证安全的平台

  3. 仓库:集中存放镜像文件的场所。DockerHub、阿里云仓库、网易云仓库等

1.2 Docker工作原理

Docker是一个Client-Server结构系统。Docker的守护进程运行在主机上。

用户通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器

基本流程如下:

  1. 用户使用Docker Client与Docker Daemon建立通信,并发送请求给后者
  2. Docker Daemon作为Docker架构中的主体部分,首先提供Docker Server的功能,使其可以接受Docker Client的请求
  3. Docker Engine执行Docker内部的一系列工作,每一项工作都是以一个Job形式存在
  4. Job运行过程中,如果需要容器镜像时,从Docker Registry中下载镜像,并通过镜像管理驱动Graph Driver将下载的镜像以Graph形式存储。
  5. 当需要为Docker创建网络环境时,通过网络管理驱动Network Driver创建并配置Docker容器网络环境。
  6. 当需要限制Docker容器运行资源或执行用户指令等操作时,通过Exec Driver完成。
  7. LibContainer是一项独立的容器管理包,Network Driver以及Exec Driver都是通过LibContainer实现具体对容器进行的操作。

1.3 CentOS 7 安装 Docker

  1. 确认当前虚拟机为CentOS 7 版本

    1
    cat /etc/redhat-release
  2. 卸载旧版Docker

    1
    2
    3
    4
    5
    6
    7
    8
    sudo yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
  3. yum安装gcc相关

    1
    2
    yum -y install gcc
    yum -y install gcc-c++
  4. yum安装说需要的软件包

    1
    yum install -y yum-utils
  5. yum设置镜像仓库

    1
    2
    3
    yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
  6. 更新yum软件包索引

    1
    yum makecache fast
  7. 安装Docker CE

    1
    yum install docker-ce docker-ce-cli containerd.io
  8. 启动Docker

    1
    systemctl start docker
  9. 测试

    1
    docker run hello-world
image-20221206014337467
  1. 卸载命令

    1
    2
    3
    4
    systemctl stop docker
    yum remove docker-ce docker-ce-cli containerd.io
    rm -rf /var/lib/docker
    rm -rf /var/lib/containerd

1.4 run命令运行流程

image-20221206015504717

1.5 为什么Docker比VM虚拟机快?

  1. docker有着比虚拟机更少的抽象层

    由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

  2. docker利用的是宿主机的内核,而不需要加载操作系统OS内核

    当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载OS,返回新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。

2. Docker常用命令

2.1 启动类命令

  1. 启动Docker

    1
    systemctl start docker
  2. 停止Docker

    1
    systemctl stop docker
  3. 重启Docker

    1
    systemctl restart docker
  4. 查看Docker状态

    1
    systemctl status docker
  5. 开机启动

    1
    systemctl enable docker
  6. 查看Docker概要信息

    1
    docker info

2.2 镜像命令

  1. 列出本地主机的镜像

    1
    2
    3
    docker images
    docker images -a
    docker images -aq
  2. 查询某个镜像

    1
    docker search [IMAGE]
  3. 拉取镜像,不加tag时默认采用最新版本latest

    1
    docker pull [IMAGE:TAG]
  4. 查看镜像/容器/数据卷所占的空间

    1
    docker system df
  5. 删除某个镜像

    1
    docker rmi [IMAGE ID]
  6. 删除所有镜像

    1
    docker rmi $(docker images -q)

2.3 容器命令

  1. 新建并启动容器

    1
    docker run [OPTIONS] **IMAGE** [COMMAND] [ARG...]

    OPTIONS说明(常用):有些是一个减号,有些是两个减号

    • –name:为容器指定一个名称
    • -d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行)
    • -i:以交互模式运行容器,通常与 -t 同时使用
    • -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;也即 启动交互式容器(前台有伪终端,等待交互)
    • -P: 随机 端口映射,大写P
    • -p: 指定 端口映射,小写p
    1
    2
    3
    4
    docker run -it ubuntu /bin/bash # 与ubuntu进行交互
    exit # 退出并停止容器
    ctrl + p + q # 退出不停止容器
    docker exec -it [CONTAINER ID] /bin/bash
    • attach 直接进入容器启动命令的终端,不会启动新的进程。用exit退出,会导致容器的停止。
    • exec 是在容器中打开新的终端,并且可以启动新的进程。用exit退出,不会导致容器的停止。
    • 一般使用 docker exec 命令,因为退出容器终端,不会导致容器的停止。
  2. 列出所有正在运行的容器

    1
    docker ps [OPTIONS] 

    OPTIONS说明(常用):

    • -a:列出当前所有 正在运行 的容器 + 历史上运行过 的
    • -l:显示最近创建的容器。
    • -n:显示最近n个创建的容器。
    • -q:静默模式,只显示容器编号。
  3. 启动已停止运行的容器

    1
    docker start [CONTAINER ID or NAME]
  4. 重启容器

    1
    docker restart [CONTAINER ID or NAME]
  5. 停止容器

    1
    2
    docker stop [CONTAINER ID or NAME]
    docker kill [CONTAINER ID or NAME] # 强制停止
  6. 停止所有容器

    1
    docker stop $(docker ps -aq)
  7. 删除容器

    1
    docker rm [CONTAINER ID]
  8. 删除所有容器

    1
    docker rm $(docker ps -aq)

2.4 Redis演示

  1. Redis前台交互式启动

    1
    docker run -it redis:6.0.8
  2. Redis后台守护式启动

    1
    2
    docker run -d redis:6.0.8
    docker logs [CONTAINER ID]
  3. 查看容器内运行的进程

    1
    docker top [CONTAINER ID]
  4. 查看容器内部细节

    1
    docker inspect [CONTAINER ID]
  5. 从容器内拷贝文件到主机上

    1
    docker cp  容器ID:容器内路径 目的主机路径
  6. 导入和导出容器

    1
    2
    docker cp  容器ID:容器内路径 目的主机路径
    cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号

3. Docker镜像

3.1 基础概念

是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。

只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持 对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承 ,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

  • 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

  • 重点理解:

    Docker镜像层都是只读的,容器层是可写的。

    当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

    所有对容器的改动都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

image-20221206131046744

3.2 commit案例

  1. Docker Ubuntu容器内执行安装vim命令

    1
    2
    apt-get update 
    apt-get -y install vim
  2. 提交新的ubuntu

    1
    docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

Docker中的镜像分层, 支持通过扩展现有镜像,创建新的镜像 。类似Java继承于一个Base基础类,自己再按需扩展。

新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层

3.3 本地镜像发布到私有库

  1. 下载镜像Docker Registry

    1
    docker pull registry
  2. 运行私有库Registry,相当于本地有个私有Docker hub

    1
    docker run -d -p 5000:5000  -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry

    默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调

  3. curl查看私有库镜像

    1
    curl -XGET http://10.249.238.5:5000/v2/_catalog
  4. 将需要发布的镜像tag修改为符合私服规范的tag

    1
    docker tag  myubuntu:0.1  10.249.238.5:5000/myubuntu:0.1 
  5. push推送到私有库

    1
    docker push 192.168.111.162:5000/zzyyubuntu:1.2 

4. Docker容器数据卷

一句话:类似Redis的数据持久化机制 RDB与AOF

将docker容器内的数据保存进宿主机的磁盘中

运行一个带有容器卷存储功能的容器实例:

1
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录   镜像名
  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接实时生效到宿主机
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

数据卷案例

  1. 映射添加数据卷

    1
    docker run -it --privileged=true -v /tmp/host_data:/tmp/docker_data --name=u1 ubuntu
  2. 在docker容器中添加文件

    1
    2
    cd /tmp/docker_data/
    touch dockerin.txt
  3. 在宿主机对应目录下查看,同步成功

    1
    2
    cd /tmp/host_data/
    ls
  4. 查看数据卷是否挂载成功

    1
    docker inspect 容器ID

读写限制:容器实例内部被限制,只能读取不能写

1
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro  镜像名

5. Docker MySQL主从复制

  1. 新建主服务器容器实例5007

    1
    docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.31
  2. 进入/mydata/mysql-master/conf目录下新建my.cnf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [mysqld] 
    ## 设置server_id,同一局域网中需要唯一
    server_id=101 
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql  
    ## 开启二进制日志功能
    log-bin=mall-mysql-bin  
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M  
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed  
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7  
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062
  3. 修改完配置后重启master实例

    1
    docker restart mysql-master
  4. 进入mysql-master容器

    1
    2
    docker exec -it mysql-master /bin/bash
    mysql -uroot -proot
  5. master容器实例内创建数据同步用户

    1
    2
    3
    4
    5
    6
    CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
    GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

    MySQL8额外步骤:
    ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
    flush privileges;
  6. 新建从服务器容器实例3308(与主机密码不要设置为一样的)

    1
    docker run -p 3308:3306 --name mysql-slave -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.31
  7. 进入/mydata/mysql-slave/conf目录下新建my.cnf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [mysqld] 
    ## 设置server_id,同一局域网中需要唯一
    server_id=102
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql  
    ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
    log-bin=mall-mysql-slave1-bin  
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M  
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed  
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7  
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062  
    ## relay_log配置中继日志
    relay_log=mall-mysql-relay-bin  
    ## log_slave_updates表示slave将复制事件写进自己的二进制日志
    log_slave_updates=1  
    ## slave设置为只读(具有super权限的用户除外)
    read_only=1
  8. 修改完配置后重启slave实例

    1
    docker restart mysql-slave
  9. 在主数据库中查看主从同步状态,得到file与position(用于从数据库配置参数)

    1
    2
    3
    4
    5
    6
    7
    8
    show master status;

    mysql> show master status;
    +-----------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +-----------------------+----------+--------------+------------------+-------------------+
    | mall-mysql-bin.000004 | 714 | | mysql | |
    +-----------------------+----------+--------------+------------------+-------------------+
  10. 在从数据库中配置主从复制

    1
    change master to master_host='10.249.238.5', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000004', master_log_pos=714, master_connect_retry=30; 

    master_host:主数据库的IP地址;

    master_port:主数据库的运行端口;

    master_user:在主数据库创建的用于同步数据的用户账号;

    master_password:在主数据库创建的用于同步数据的用户密码;

    master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;

    master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;

    master_connect_retry:连接失败重试的时间间隔,单位为秒。

  11. 在从数据库中开启主从同步

    1
    start slave;
  12. 查看从数据库状态,发现已同步

    1
    2
    3
    show slave status;
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes

6. 分布式存储

6.1 哈希取余分区

2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:

hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

优点:简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。

缺点:原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。 某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

6.2 一致性哈希算法分区

  1. 构建一致性哈希环

    一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),这样让它逻辑上形成了一个环形空间。

  2. 将集群中各个IP节点映射到环上的某一个位置。

    将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。

  3. 当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置, 从此位置沿环顺时针行走,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

优点:

  • 容错性:假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则 受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据 ,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。

    image-20221207143658100
  • 扩展性:数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可, 不会导致hash取余全部数据重新洗牌。

    image-20221207143624648

缺点:Hash环的数据倾斜问题

一致性Hash算法在服务 节点太少时 ,容易因为节点分布不均匀而造成 数据倾斜 (被缓存的对象大部分集中缓存在某一台服务器上)

7. Docker Redis集群搭建

7.1 主从搭建

  1. 搭建Redis集群

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6381 
     
    docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6382
     
    docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6383
     
    docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6384
     
    docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6385
     
    docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6386
  2. 进入容器,为集群构建主从关系

    1
    2
    3
    docker exec -it redis-node-1 /bin/bash

    redis-cli --cluster create 10.249.238.5:6381 10.249.238.5:6382 10.249.238.5:6383 10.249.238.5:6384 10.249.238.5:6385 10.249.238.5:6386  --cluster-replicas 1
image-20221207153624644
  1. 通过 redis-cli -p 6381 -c 命令进入集群,以防止路由失效
  2. 通过命令 redis-cli --cluster check 10.249.238.5:6381 查看集群状态
  3. 主从切换:主机宕机,从机上位

7.2 主从扩容

  1. 新建两个Redis节点

    1
    2
    3
    docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6387 

    docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.16 --cluster-enabled yes --appendonly yes --port 6388
  2. 进入6387容器内部

    1
    docker exec -it redis-node-7 /bin/bash

    将新增的6387节点作为master节点加入集群

    1
    2
    3
    # 6387 就是将要作为master新增节点 
    # 6381 就是原来集群节点里面的领路人
    redis-cli --cluster add-node 10.249.238.5:6387 10.249.238.5:6381
  3. 检查集群情况

    1
    redis-cli --cluster check 10.249.238.5:6381
    image-20221207171056093
  4. 重新分派槽号

    4台机器:平分之后为4096

    1
    redis-cli --cluster reshard 10.249.238.5:6381

    为什么6387是3个新的区间,以前的还是连续?

    重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387

image-20221207171611411
  1. 为主节点6387分配从节点6388

    1
    redis-cli --cluster add-node 10.249.238.5:6388 10.249.238.5:6387 --cluster-slave --cluster-master-id b8fbe4eba45cb5f8c44eca3fe15e0a96d927d27c

7.3 主从缩容

将添加的两个节点6387和6388下线(先删从节点,再删主节点)

  1. 将6388删除

    1
    redis-cli --cluster del-node 10.249.238.5:6388 67673fee431f0146671773da6326076bb8b30343
  2. 将6387的槽号清空,重新分配。这里全部分配给6382

    1
    redis-cli --cluster reshard 10.249.238.5:6381 
  3. 将6387删除

    1
    redis-cli --cluster del-node 10.249.238.5:6387 b8fbe4eba45cb5f8c44eca3fe15e0a96d927d27c

8. DockerFile

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

8.1 DockerFile基础

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. 表示注释
  4. 每条指令都会创建一个新的镜像层并对镜像进行提交

执行DockerFile基本流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成
image-20221207174219551

8.2 DockerFile常见保留字

8.3 DockerFile自定义镜像

需要指定centos版本,并且 RUN yum -y install glibc不加版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FROM centos:7
MAINTAINER ltyzzz<ltyzzz2000@gmail.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u331-linux-aarch64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_331
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80

CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash

8.4 DockerFile虚悬镜像

仓库名、标签都是的镜像,即dangling image

编写虚悬镜像步骤

  1. 编写Dockerfile文件

    1
    2
    3
    4
    vim Dockerfile

    from ubuntu
    CMD echo 'action is success'
  2. 构建镜像

    1
    docker build .
  3. 查看虚悬镜像

    1
    docker image ls -f dangling=true

9. Docker部署模块

9.1 部署过程

通过打包Springboot项目得到jar包,并通过Dockerfile生成镜像,以容器形式运行在虚拟机上

  1. 打包Springboot项目:package

  2. 在虚拟机中的/mydocker目录下编写Dockerfile文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 基础镜像java
    FROM openjdk:8
    # 作者
    MAINTAINER lty
    # VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
    VOLUME /tmp
    # 将jar包添加到容器中并更名为zzyy_docker.jar
    ADD docker-demo-0.0.1-SNAPSHOT.jar lty_docker.jar
    # 运行jar包
    RUN bash -c 'touch /lty_docker.jar'
    ENTRYPOINT ["java","-jar","/lty_docker.jar"]
    #暴露6001端口作为微服务
    EXPOSE 6001
  3. 将生成的jar包拖动到虚拟机mydocker目录下

  4. 通过如下命令生成镜像

    1
    docker build -t lty_docker:1.0 .
  5. 以容器方式后台运行

    1
    docker run -d -p 6001:6001 376a8091251b

9.2 容器通信bug

主机中的容器失去与外界容器的连接:

  1. 主机可以与其他主机通信。
  2. 在主机中运行的容器无法与其他主机通信。

后台运行通过Dockerfile打包的Springboot镜像后提示:

1
WARNING: IPv4 forwarding is disabled. Networking will not work.

解决方案:

  1. 将以下内容添加到 /etc/sysctl.conf 中

    1
    net.ipv4.ip_forward=1
  2. 重启网络服务

    1
    service network restart

10. Docker网络

docker启动后,会建立一个名为docker0的虚拟网桥,可用ifconfig命令查看

  • 容器间的互联和通信以及端口映射
  • 容器IP变动时候可以通过服务名直接网络通信而不受到影响

10.1 网络命令

  1. 查看网络

    1
    docker network ls
  2. 查看网络源数据

    1
    docker network inspect  XXX网络名字
  3. 删除网络

    1
    docker network rm XXX网络名字

10.2 网络模式

  1. bridge模式:使用–network bridge指定,默认使用docker0
    • Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在 内核层 连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到 同一个物理网络 。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码, 让主机和容器之间可以通过网桥相互通信。
  2. host模式:使用–network host指定
    • 直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。
  3. none模式:使用–network none指定
    • 在none模式下,并不为Docker容器进行任何网络配置。 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo。需要我们自己为Docker容器添加网卡、配置IP等。
  4. container模式:使用–network container:NAME或者容器ID指定
    • 新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

11. Docker-Compose

Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

11.1 Linux Arm64 安装Docker-Compose

Docker-Compose目前没有arm64版本,目前只支持pip安装

  1. 安装apt-get

    • apt-get命令是ubuntu等操作系统的安装命令,和yum为同类

    下载apt-get

    1
    curl https://raw.githubusercontent.com/dvershinin/apt-get-centos/master/apt-get.sh -o /usr/local/bin/apt-get

    修改权限

    1
    chmod 0755 /usr/local/bin/apt-get
  2. 安装Docker Compose

    1
    2
    3
    4
    5
    6
    7
    8
    sudo apt-get update -y
    sudo apt-get upgrade -y
    sudo apt-get install curl python3-pip libffi-dev python-openssl libssl-dev zlib1g-dev gcc g++ make -y
    curl -sSL https://get.docker.com/ | sh
    sudo snap install rustup --classic
    sudo apt install rustc
    sudo pip3 install docker-compose
    sudo docker-compose --version

    sudo pip3 install docker-compose命令报错时,执行如下命令,然后再重新安装

    1
    sudo -H pip3 install --upgrade pip

11.2 Compose核心概念

服务:一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器

工程:由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

11.3 Compose使用步骤

  1. 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
  2. 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务。
  3. 执行 docker-compose up 命令 来启动并运行整个应用程序,完成一键部署上线

11.4 Compose常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Compose 常用命令 
docker-compose -h                           #  查看帮助
docker-compose up                           #  启动所有 docker-compose服务
docker-compose up -d                        #  启动所有 docker-compose服务 并后台运行
docker-compose down                         #  停止并删除容器、网络、卷、镜像。
docker-compose exec  yml里面的服务id                 # 进入容器实例内部  docker-compose exec  docker-compose.yml文件中写的服务id  /bin/bash
docker-compose ps                      # 展示当前docker-compose编排过的运行的所有容器
docker-compose top                     # 展示当前docker-compose编排过的容器进程
docker-compose logs  yml里面的服务id     #  查看容器输出日志
docker-compose config     #  检查配置
docker-compose config -q  #  检查配置,有问题才有输出
docker-compose restart   #  重启服务
docker-compose start     #  启动服务
docker-compose stop      #  停止服务

12. Docker Portainer

安装命令

1
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

通过虚拟机访问Portainner


Docker学习笔记
https://ltyzzzxxx.github.io/2022/12/10/Docker学习笔记/
作者
周三不Coding
发布于
2022年12月10日
许可协议