docker学习

312 阅读3分钟

docker

介绍

docker 是一个容器,基于进程封装隔离的虚拟化技术。容器是一个技术类型,docker则是当下最流行的一个容器方案。

docker和其他容器与传统容器最大的区别在于,一个是系统级,一个是进程级。

Docker 底层技术主要包括 Namespaces,Cgroups 和 rootfs。
Cgroups 控制组技术是用来限制、记录和隔离系统资源(包括CPU、内存、磁盘输入输出等)分配的关键技术。 Namespaces 用来隔离容器。

Docker官方文档

docker 可以快速构建、分享、运行应用。而且是跨平台、进程隔离的。

核心概念:

  • network:网络
  • volume:卷
  • image:镜像
  • container:容器

安装

首先安装docker环境,安装后的主机叫docker主机或者docker host

参照官网文档安装即可。
配置docker安装源,因为国内网络环境,直接下载会比较慢。

# 配置docker yum源。
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 启动& 开机启动docker; enable + start 二合一
systemctl enable docker --now

配合镜像源地址,可以加速下载。

# 配置加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
      "https://docker.m.daocloud.io",
      "https://hub-mirror.c.163.com",
      "https://mirror.baidubce.com",
      "https://your_preferred_mirror",
      "https://dockerhub.icu",
      "https://docker.registry.cyou",
      "https://docker-cf.registry.cyou",
      "https://dockercf.jsdelivr.fyi",
      "https://docker.jsdelivr.fyi",
      "https://dockertest.jsdelivr.fyi",
      "https://mirror.aliyuncs.com",
      "https://dockerproxy.com",
      "https://mirror.baidubce.com",
      "https://docker.m.daocloud.io",
      "https://docker.nju.edu.cn",
      "https://docker.mirrors.sjtug.sjtu.edu.cn",
      "https://docker.mirrors.ustc.edu.cn",
      "https://mirror.iscas.ac.cn",
      "https://docker.rainbond.cc"
    ]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

查看版本

docker --version

查看帮助

docker cmd --hlep

基本操作

镜像操作

下载镜像
docker pull image_name:tag
查看本地镜像
docker images
删除一个镜像
docker rmi image_id

i 表示 镜像(image)

查看具体镜像的历史记录
docker history image_id

可以查看镜像的构建历史,包括每一步的操作。
因为镜像的构建过程,就是一层层叠加起来的。

容器操作

创建容器

创建容器并不会启动,只有运行才会启动。

docker create [option] image
运行容器(在容器中执行一个命令)

运行容器时会创建并启动。

docker run [option] image [command] [arg...]

但这样的启动,占用当前会话窗口,一旦退出,容器也会停止。所以需要加一些参数

docker run -d --name myimage -p 80:80 image

上面的命令表示,创建一个名为myimage的后台运行容器,并且将容器的80端口映射到宿主机的80端口。

  • -d 表示后台运行
  • --name 表示容器名
  • -p 表示端口映射
  • -v 表示挂载目录或卷 有2种模式:
    • -v /宿主机目录:/容器目录 表示挂载目录
    • -v 卷名:/容器目录 表示挂载卷
  • --network 表示指定网络
查看运行中的容器
docker ps
查看所有的容器
docker ps -a
启动一个容器
docker start container_id
停止一个容器
docker stop container_id

停止多个容器,可以使用docker stop $(docker ps -q)

重启一个容器
docker restart container_id
删除一个容器
docker rm container_id

-f 表示强制删除正在运行的容器

查看容器的日志
docker logs container_id
  • -f 表示实时查看日志
  • -t 表示显示时间戳

顺便提一下,查看docker引擎日志:
如果是CentOS,可以使用journalctl -u docker.service查看。

查看容器的状态
docker stats container_id
进入容器(在容器中执行一个命令)
docker exec -it container_id /bin/bash

-it 表示进入交互模式,-i 表示标准输入,-t 表示分配一个伪终端。
/bin/bash 表示进入容器后使用bash,可简写为bash

docker attach 进入容器,但退出时,容器会停止。docker exec则不会

分享社区

登录
  1. 登录docker hub,获取用户名和密码

  2. 命令行登录,会提示输入用户名和密码

    docker login
    
命名
docker tag image username/image:tag
推送
docker push username/image:tag

建议推送一个最新版的,例如命名为 hlw/image:latest

存储

目录挂载

可以解决,容器内数据持久化问题,数据修改方便。容器停止后,数据还在宿主机上。

启动时添加参数

-v /宿主机目录:/容器内目录
卷映射

初始是以里面的目录为准,容器里面的东西,外面也会有。启动后可以随便改,2边一样。

启动时添加参数

-v 卷名:/容器内目录

启动后,统一放在 /var/lib/docker/volumes/卷名 目录下

对于mac用户,docker 虚拟机才是我创建容器的真正的宿主机,所以需要进入虚拟机内部操作。如下命令,可以进入虚拟机内部,查看卷映射的目录。

stty -echo -icanon && nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock && stty sane # ls -al /var/lib/docker/overlay2/

目录挂载与卷映射的区别:

  1. 写法上:目录挂载用的是宿主机路径,卷映射用的是卷名。
  2. 卷可以被docker管理,可以备份、迁移。
  3. 目录挂载性能更好,灵活性高;卷相反

绑定挂载和数据卷的传播覆盖原则

  • 当绑定挂载和数据卷是空的时候,容器内目录的内容会传播到数据卷中
  • 当绑定挂载和数据卷都不是空的时候,容器内目录的内容会被数据卷中的内容覆盖

使用 docker volume 命令可以管理卷

网络

docker的网络模式,用来解决容器与容器之间、容器与宿主机之间的通信问题。
默认他们是不互联互通的

docker每启动一个容器,都会自动分配一个虚拟的私有网络。使用容器的ip加端口可以互相访问。 docker0是默认的网络。不支持域名访问
自己创建网络,在容器内部可以使用容器名来互相访问

docker的网络模式:

  • bridge:桥接模式,默认的网络。缺点:宿主机以外的世界无法访问
  • host:主机模式,容器与宿主机共享网络。
  • none:无网络模式,容器没有网络。
  • container:容器模式,容器与另一个容器共享网络。
创建自定义网络
docker network create --driver bridge mynet

--driver 表示驱动,默认为bridge

启动容器时指定网络
docker run -d --name myimage --network mynet image

--network 表示指定网络

Docker Compose

批量管理容器的工具

  1. 创建一个compose.yml文件
  2. 参照官方文档编写

上线:docker compose up -d
下线: docker compose down
启动: docker compose start x1 x2 其他

  1. 更新yaml文件,再重上线只会启动修改的容器

默认

构建镜像

当从hub中下载的镜像,不能满足需求时,就需要构建自己的镜像了。
一般有2种方法:

  1. 使用docker commit命令,提交更改
  2. 使用docker build + Dockerfile构建

保存镜像-文件

提交镜像

将容器的存储层保存为镜像文件。相当于在原有镜像的基础上,新增了一层。

docker commit -m "change something" container_id newimage:tag

-m 表示提交的描述信息

备注:不推荐使用这种方式,因为这种在存储层修改的东西有很多文件改动和添加,会导致镜像及其臃肿;另外在存储层的操作都是黑箱操作,只有制作镜像的人知道,但时间一长也很快忘记,后期维护也很痛苦。

保存为文件
docker save image -o file.tar

-o 表示输出文件

从文件加载镜像
docker load -i file.tar

Dockerfile

构建自定义镜像

  1. 编写Dockerfile 如何编写Dockerfile,参照官方文档说明编写
    官方文档
  2. 构建镜像
    1. docker build -f Dockerfile -t image:tag .

镜像分层存储 基础组件可以公用,节省空间

最佳实践

  1. 启动一个容器,需要考虑(参照官方文档说明编写)
    1. 有没有端口需要映射出来,使用 -p 参数
    2. 有没有目录或者配置文件需要映射出来,使用 -v 参数
    3. 需不需要传入一个环境变量,使用 -e 参数

操作实践

搭建nginx服务

任务:

  1. 搭建一个nginx服务,端口映射到8080,
  2. 并且进行目录挂载,将nginx的默认页面改为自定义页面。
  3. 将配置文件映射到宿主机,方便修改。

操作步骤:

  1. 官网查找镜像

  2. 下载镜像
    docker pull nginx
    docker images //查看镜像

  3. 运行容器

        docker run -d --name mynginx -p 8080:80 \
        -v /Users/hlw/docker-workspace/nginx-html:/usr/share/nginx/html \
        -v nginx-conf:/etc/nginx nginx
    
        docker ps // 查看容器
        docker exec -it mynginx bash // 进入容器
        docker stop mynginx // 停止容器
        docker start mynginx // 启动容器
        docker logs mynginx // 查看日志
        docker rm -f mynginx // 删除容器
    

搭建 redis 主从集群

任务:

  1. 搭建一个redis主从复制环境,端口映射到6379和6380。
  2. 数据持久化到宿主机上。
  3. 使用自定义网络。

操作步骤:

  1. 官网查找镜像
    docker pull redis
    docker images //查看镜像

  2. 创建自定义网络 docker network create --driver bridge mynet

    这一步主要是让他们在同一个网络中

  3. 创建挂载目录

    1. 主节点

      1. 创建数据目录 mkdir -p /Users/hlw/docker-workspace/app/rd2/data
        创建配置文件 mkdir -p /Users/hlw/docker-workspace/app/rd2/conf

      2. 编写配置文件 /Users/hlw/docker-workspace/app/rd2/conf/redis.conf

        # 服务端口 默认6379
        port 6379
        # 关闭保护模式,允许远程连接
        protected-mode no
        # 密码
        requirepass 123456
        
    2. 从节点

      1. 创建数据目录 mkdir -p /Users/hlw/docker-workspace/app/rd1/data
        创建配置文件 mkdir -p /Users/hlw/docker-workspace/app/rd1/conf

      2. 编写配置文件 /Users/hlw/docker-workspace/app/rd1/conf/redis.conf

        # 服务端口 默认6379
        port 6379
        # 关闭保护模式,允许远程连接
        protected-mode no
        # 密码
        requirepass 123456
        # 主节点密码
        masterauth 123456
        
        # 配置主从复制 从节点默认只读
        ## redis5.0后新版本配置
        replicaof redis01 6379
        ## redis5.0之前配置,新版本Redis也还可以用,我部署时确定6.0版本还是可用的
        # slaveof 172.16.8.186 6379
        

        replicaof redis01 6379 这里的 redis01 就是主节点的容器名,要和自定义网络中的容器名一致。

  4. 运行容器

    1. 创建主节点

      docker run -d -p 6379:6379 \
      -v /Users/hlw/docker-workspace/app/rd2/data:/data \
      -v /Users/hlw/docker-workspace/app/rd2/conf/redis.conf:/etc/redis/redis.conf \
      --network mynet --name redis01 \
      redis \
      redis-server /etc/redis/redis.conf
      

      redis-server /etc/redis/redis.conf 指定配置文件以启动redis-server进程

    2. 创建从节点

      docker run -d -p 6380:6379 \
      -v /Users/hlw/docker-workspace/app/rd1/data:/data \
      -v /Users/hlw/docker-workspace/app/rd1/conf/redis.conf:/etc/redis/redis.conf \
      --network mynet --name redis02 \
      redis \
      redis-server /etc/redis/redis.conf
      

搭建redis集群

redis集群使用相当广泛,拥有数据分片,负载均衡,高可用,故障恢复等特性。

任务:搭建一个3主3从的redis集群

简要步骤:

  1. 创建网络
  2. 创建结点目录,目录包含配置文件和数据目录
  3. 编写配置文件
  4. 启动redis容器结点
  5. 使用redis-cli命令创建集群
  6. 验证
创建网络
docker network create redis-net

默认桥接模式,宿主机之外无法访问内部redis

创建结点目录
mkdir -p {7000,7001,7002,7003,7004,7005}/conf
编写配置文件
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip <host-ip>
# 根据节点修改(7000-7005)
cluster-announce-port 7000  
# 根据节点修改(17000-17005)
cluster-announce-bus-port 17000  
appendonly yes

<host-ip> 替换为宿主机IP,文件保存到 7000/conf 目录下,其他节点同理。

启动redis容器结点
for port in 7000 7001 7002 7003 7004 7005; do
  docker run -d \
    --name redis-${port} \
    --net redis-net \
    -p ${port}:6379 \
    -p 1${port}:16379 \
    -v $(pwd)/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
    -v $(pwd)/${port}/data:/data \
    redis redis-server /usr/local/etc/redis/redis.conf
done
使用redis-cli命令创建集群
redis-cli --cluster create \
  <host-ip>:7000 \
  <host-ip>:7001 \
  <host-ip>:7002 \
  <host-ip>:7003 \
  <host-ip>:7004 \
  <host-ip>:7005 \
  --cluster-replicas 1
验证
# 连接任意结点
redis-cli -c -h localhost -p 7000
cluster nodes
cluster info

参考文献

  1. 《Docker快速入门》- 赵荣娇