docker基础

docker

主要就是了解一下docker和虚拟机的区别

docker原理

docker常见的操作

1、docker和虚拟机的区别

1、操作系统的组成部分

  • 内核空间:

    • 进程管理

    • 驱动管理

    • 还有其他的

  • 用户空间:

    • shell 命令行管理

    • GUI 图形化界面管理

  • 系统调用指的就是使用shell或者其他的调用内核的一些参数

2、容器和虚拟机的区别

  • 容器:

    • 容器的操作系统是一个阉割版的操作系统,只包含操作系统的用户空间,以及要部署的软件和相关的依赖

    • 一台宿主机上面的所有容器都共用同一个宿主机内核

    • 性能更高,隔离性差

    • 容器提供应用级别的服务

      • redis镜像

      • mysql镜像

      • nginx镜像

    • 容器就是为了任务而生的

  • 虚拟机

    • 虚拟机是一个完整的操作系统

    • 较大的性能损耗

    • 提供Iass层服务镜像

      • ubuntu 22.04镜像

      • centos 7 镜像

  1. 虚拟化层级

    • docker:操作系统虚拟化,利用宿主机的操作系统内核,通过这个容器引擎创建隔离的用户空间,所有容器共享同一个内核,只需要安装对应的程序和依赖项即可

    • 虚拟机:硬件虚拟化,通过hypervisor(vmware,virtualbox,kvm)模拟完整的硬件环境,虚拟机控制器,每一个虚拟机都有独立的操作系统内核,驱动程序和应用程序

  2. 资源占用

    • docker: 容器共享内核,不需要额外的操作系统的开销,资源占用少,启动速度快

    • 虚拟机:每个虚拟机都包含完整的操作系统,资源占用大,启动速度慢

  3. 性能:

    • docker: 由于直接利用宿主机的内核和硬件资源,性能接近原生应用程序

    • 虚拟机:由于Hypervisor层的存在,以及每个虚拟机都需要运行独立的操作系统,性能有一定损耗。

  4. 隔离性:

    • Docker:容器之间的隔离是基于Linux内核的命名空间(Namespaces)和控制组(cgroups),隔离性相对较弱,但足够满足大多数应用场景。如果一个容器被攻破,可能会影响其他容器。

    • 虚拟机:每个虚拟机都运行独立的操作系统,隔离性强。一个虚拟机被攻破不会影响其他虚拟机。

  5. 移植性:

    • Docker:通过Docker镜像,可以轻松地在不同环境中部署相同的应用,实现"一次构建,到处运行"。

    • 虚拟机:虚拟机镜像通常依赖于特定的Hypervisor和硬件配置,移植性较差。

  6. 应用场景:

    • Docker:适合微服务架构、持续集成/持续部署(CI/CD)、开发测试环境隔离等场景。

    -虚拟机:适合需要完全隔离的应用,如多租户环境、遗留应用迁移、不同操作系统共存等场景。

2、docker安装和工作原理

  • 二进制安装

  • yum安装

img

  • 是一个c/s架构

  • 客户端线程本地拉取镜像,没有的话,从镜像仓库里面进行拉取

  • 通过这个docker的守护进程管理容器

2、docker镜像

1、镜像的命名规则

  • registry/namespace/image:tag

  • docker.io/libary/httpd:latest

    • regitry: 仓库地址

    • namespace: 命名空间,里面存储镜像

    • image: 镜像的名字

    • tag: 镜像标签,镜像版本

  • 就是一个仓库(registry),里面有不同的房间(namespace),不同的房间存储不同的货物(image)

  • 不需要加上https:// docker默认加上了

2、镜像管理

# 列出本地镜像

docker images

# 拉取镜像

docker pull 镜像

# 删除镜像

docker rmi 镜像

# -f 强制删除镜像,就是这个容器正在使用这个镜像

# 但是了,不会删除掉容器

3、镜像仓库

  • 有dockerhub 或者私有仓库

  • 比如在华为云,阿里云上面搭建自己的镜像仓库

# 首先登陆镜像仓库
docker login 华为云/阿里云

# 为镜像重新命名

# 符合这个仓库的命名规则,才能将自己的镜像推送上去
# 在华为云上面创建组织(命名空间)
docker tag httpd:latest 镜像仓库地址/命名空间/image:tag

# 推送镜像

docker push 镜像


4、镜像加速器

  • 设置了镜像加速器的话,就从这个里面拉取镜像即可
{
"registry-mirrors": ["镜像加速器"]
}

3、容器管理

1、运行容器

  • tid选项
# t 就是分配一个终端tty

# i 交互式

# d 放在后台运行,不占用前台的终端

# /bin/sh 给了这个容器一个任务
[root@server docker]# docker run -tid --name b1 busybox:latest /bin/sh

# 不给任务的的话,执行容器的默认任务(命令) sh

[root@server docker]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5b27e6539ea4        busybox:latest      "sh"                2 seconds ago       Up 1 second                             b2
c0b790da860e        busybox:latest      "/bin/sh"           4 minutes ago       Up 4 minutes                            b1

  • exec 进入容器
# /bin/sh 分配了一个终端才能进入
[root@server docker]# docker exec -ti b1 /bin/sh
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # 

# 退出这个容器,容器不会停止,因为分配了一个终端,不会覆盖容器默认的命令

2、端口映射

  • 容器是为了一个任务而生的,因此运行一个nginx容器提供网页,容器创建出来有自己的ip地址,相关的资源
# 运行了一个容器,查看ip地址为172.17.0.2
[root@server ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7af8f33f1c72        nginx:latest        "/docker-entrypoint.…"   40 seconds ago      Up 39 seconds       80/tcp              elastic_babbage

# 在宿主机上面进行访问

[root@server ~]# curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>

# 但是了跨主机是访问不到的,客户端访问不到的,因此需要做端口映射才行
  • 因此的话,就需要这个端口映射,端口映射就能实现外部直接访问宿主机的ip+端口就能访问到容器内部运行的服务了
# -p 宿主机端口:容器端口
# 将8080端口映射到容器内部的80端口上了
[root@server ~]# docker run -tid  -p 8080:80 nginx
a2f6386e1aa06a9d9602eb9bc9a907ccd78e48bb375f775f1280c870a36bd9c7

do[root@server ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
a2f6386e1aa0        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:8080->80/tcp   distracted_keller
7af8f33f1c72        nginx:latest        "/docker-entrypoint.…"   4 minutes ago       Up 4 minutes        80/tcp                 elastic_babbage

# -P 将容器的端口随机映射到宿主机上面


img

  • 这个端口映射的原理
# 做了一个DNA
# 访问宿主机的8080端口转发到容器内部的80端口上了

iptables -t nat -L -n  

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.3:80

3、环境变量

就是有些容器启动的时候,需要传入环境变量才能启动的

  • 例如这个mysql容器,启动的时候,必须添加数据库的密码才行
[root@server /]# docker run -tid --name m1 -e MYSQL_ROOT_PASSWORD=123 uhub.service.ucloud.cn/qwimages/mysql:latest 

[root@server /]# mysql -uroot -p123 -h 172.17.0.2 -P3306
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 9.5.0 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 

4、docker存储

创建一个容器出来,我们在容器里面进行的操作,写入等等都是写入到一个临时的存储空间上面,删除容器的时候,镜像还是存在的,删除的是容器的临时空间

如果是存储数据库的文件的话,删除的话,就找不到了
因此的话就有了持久化存储了

常见的是目录挂载,可以指定读写权限,将宿主机的目录挂载到容器内部的存储数据的目录上即可
如果宿主机目录不存在的话,会自动的创建,容器里面也是这样的

[root@server ~]# docker run -tid --name n1 -v /root/index.html:/usr/share/nginx/html/index.html -P nginx
f5fa405252c44165f8a39f8dc374025af8926b2f3d595385a8ae2c70a30e1766

[root@server ~]# curl localhost:32768
123

# 修改这个index.html 容器里面的数据也会被修改

但是了,如果在容器里面进行删除的话,那么这个宿主机上面的数据也会被删除,因此的添加一个ro权限

[root@server ~]# docker run -tid --name n2 -v /tmp/:/data:ro nginx
d0d59ece9b88c8c7b4777c6c4d83edc8286ee89efe338e70e9bb339464048a8c
[root@server ~]# docker exec -ti n2 /bin/bash
root@d0d59ece9b88:/# cd /data/
root@d0d59ece9b88:/data# ls
systemd-private-ed558b8db37947e99aab459f3f501e69-chronyd.service-8SlgwA
systemd-private-ed558b8db37947e99aab459f3f501e69-systemd-logind.service-cALe9S
# 写入不了文件,只读的挂载
root@d0d59ece9b88:/data# echo 13 > 1.txt
bash: 1.txt: Read-only file system

# 但是宿主机可以修改

卷挂载,匿名卷和命名卷
默认创建出来的卷就是匿名卷
指定卷的名字就是命名卷

5、docker网络

安装docker的时候,已经创建出来一个默认的网桥docker0
这个网桥会自动的为创建出来的容器分配ip地址,充当这个dhcp的作用

# 网段是172.0.0.1
[root@server /]# ifconfig  docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:9bff:fe2c:45f2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:9b:2c:45:f2  txqueuelen 0  (Ethernet)
        RX packets 81  bytes 9769 (9.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 107  bytes 10031 (9.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

host网络模式,直接使用宿主机的网络,性能是最高的
缺点就是会占用宿主机的端口,容器造成端口冲突

# 查看网络信息,直接宿主机的网络
[root@server /]# docker run -tid --name b1 --network host  busybox:latest 
da3d2f5e2febfcde888c0228078f4a9b1fc56f48c3a4f6b07b6e2a54435da02c
[root@server /]# docker exec -ti b1 /bin/sh
/ # ifconfig 
docker0   Link encap:Ethernet  HWaddr 02:42:9B:2C:45:F2  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:9bff:fe2c:45f2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:83 errors:0 dropped:0 overruns:0 frame:0
          TX packets:109 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:9825 (9.5 KiB)  TX bytes:10115 (9.8 KiB)

ens33     Link encap:Ethernet  HWaddr 00:0C:29:FE:CB:8E  
          inet addr:192.168.50.20  Bcast:192.168.50.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fefe:cb8e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:209671 errors:0 dropped:0 overruns:0 frame:0
          TX packets:24711 errors:0 dropped:0 overruns:0 carrier:0

bridge网络模式是最常见的,可以进行端口映射,nat转发,但是了在传输的过程中性能会有损耗

# 指定网段,网关
docker network create  --driver bridge --subnet 173.0.0.0/24 --gateway 173.0.0.1  b1

[root@server /]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
70e7306eb9cd        b1                  bridge              local
111a03cb769c        bridge              bridge              local
f70c061fd48b        host                host                local
fbe5deb122ae        none                null                local


docker run -tid --name b1 --network b1 busybox

# 2个网段之间的通信的话,就需要一个容器连接另外一个网桥才能实现通信
docker network connect bridge b1

net.ipv4.ip_forward = 1 这个内核参数需要开启,ipv4转发的参数

6、docker-compose

容器编排工具,将创建容器的相关的命令都存储在这个文件上面
非常的便捷
能够同时启动多个容器,对多个容器进行操作

  • 一个实验wordpress
[root@server mnt]# cat wordpress.yml 
version: "2.2"  # 版本需要指定,不同的版本支持不同的参数,不添加这个的话,默认使用的是version1版本的,
services:  # 服务名
  wordpress:  # 第一个容器
    image: uhub.service.ucloud.cn/qwimages/wordpress:latest
    container_name: web  # 指定容器的名字
    ports:  # 指定容器的端口
      - "8080:80"
    links:  # 给容器起一个别名,db是容器名,web-db是容器的别名
      - db:web-db
    depends_on:   # 先启动哪一个容器,自己才能启动
      - db
    environment:  # 环境变量
      - WORDPRESS_DB_HOST=web-db  # 连接数据库地址
      - WORDPRESS_DB_USER=root  # 连接数据库用户名
      - WORDPRESS_DB_PASSWORD=root  # 连接数据库的密码
      - WORDPRESS_DB_NAME=wordpress  # 连接数据库的库
  db:
    image: uhub.service.ucloud.cn/qwimages/mysql:latest
    container_name: d1
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=root  # 数据库的密码
      - MYSQL_DATABASE=wordpress  # 创建的数据库

# 启动容器,指定yaml文件
docker-compose -f wordpress.yml up -d

# 删除容器,会删除容器的卷,网络信息
[root@server mnt]# docker-compose -f wordpress.yml down -v
Stopping web ... done
Stopping d1  ... done
Removing web ... done
Removing d1  ... done
Removing network mnt_default

7、容器的生命周期

  • 创建,启动,暂停,退出,删除

6、问题排查

有的时候,容器会出现问题,就需要进行排查
docker inspect container_id 查看errors字段,如果没有的话,就是正常的退出,而不是这个容器自身的原因了
docker logs container_id 查看容器的日志信息

总结

  • podman docker-podman 用docker来管理podman
posted @ 2026-03-12 16:54  乔的港口  阅读(1)  评论(0)    收藏  举报