docker概述及镜像管理

dockers概述

docker官方网站

docker官网:https://www.docker.com/

docker镜像仓库:https://hub.docker.com/

什么是docker?

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

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

docker的作用:

简化程序部署

Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的 任务,在Docker容器的处理下,只需要数秒就能完成。

避免选择恐惧症

如果你有选择恐惧症,还是资深患者。Docker 帮你 打包你的纠结!比如 Docker 镜像;

Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如 Web 应用、后台应用、数据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。

节省开支

一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然

高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。

持续交付和持续部署

对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像

更轻松的迁移

由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况

docker的使用场景

  • Web 应用的自动化打包和发布。
  • 自动化测试和持续集成、发布。
  • 在服务型环境中部署和调整数据库或其他的后台应用。
  • 从头编译或者扩展现有的 OpenShi或 Cloud Foundry 平台来搭建自己的 PaaS 环境。

docker和虚拟机的区别


实现原理不同

虚拟机是⽤来进⾏硬件资源划分的完美解决⽅案,利⽤的是硬件虚拟化技术,如此VT-x 、AMD-V会通 过⼀个 hypervisor 层来实现对资源的彻底隔离。 而容器则是操作系统级别的虚拟化,利⽤的是内核的 Cgroup 和 Namespace 特性,此功能通过软件 来实现,仅仅是进程本身就可以实现互相隔离,不需要任何辅助。

使用资源不同

Docker 容器与主机共享操作系统内核,不同的容器之间可以共享部分系统资源,因此更加轻量级, 消耗的资源更少。 虚拟机会独占分配给⾃⼰的资源,不存在资源共享,各个虚拟机之间近乎完全隔离,更加重量级,也会消耗更多的资源。

应用场景不同

若需要资源的完全隔离并且不考虑资源的消耗,可以使用虚拟机。 若是想隔离进程并且需要运行大量进程实例,应该选择 Docker 容器。

docker的基本概念

Docker 包括三个基本概念

  • 镜像
  • 容器
  • 仓库

docker镜像

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变,可以理解为一个只读的文件系统

分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 UnionFS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。

在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像

docker容器

镜像( Image )和容器( Container )的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。

容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。

前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume) 、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失

docker仓库

Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。

Docker Hub( https://hub.docker.com ) 提供了庞大的镜像集合供使用。

Docker仓库又分公有仓库和私有仓库

公有仓库

Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像使用的就是这个服务。

由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务( Registry Mirror ),这些镜像服务被称为加速器。常见的有 阿里云加速器、DaoCloud 加速器 等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从 Docker Hub 下载速度会提高很多。国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库 等。

docker安装

环境

IP 规格 系统
10.0.0.10 2c4g Ubuntu22.04

安装操作

这里借用阿里云镜像仓库镜像安装
https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.57e31b11y0XHUO

复制代码
# step 1: 安装必要的一些系统工具
sudo apt-get update -y
sudo apt-get install ca-certificates curl gnupg -y

# step 2: 信任 Docker 的 GPG 公钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Step 3: 写入软件源信息
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
# Step 4: 安装Docker
sudo apt-get update -y
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
#   docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
#   docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]

验证是否安装成功

复制代码
[root@lb ~]# systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2025-04-12 13:12:11 CST; 6s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 17627 (dockerd)
      Tasks: 7
     Memory: 30.1M
        CPU: 207ms
     CGroup: /system.slice/docker.service
             └─17627 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

[root@lb ~]# docker --version
Docker version 28.0.4, build b8034c0

配置阿里云镜像加速(可选操作)

地址:
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

配置其它镜像加速器(强烈推荐!!!)

复制代码
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.mybacc.com",
    "https://dytt.online",
    "https://lispy.org",
    "https://docker.xiaogenban1993.com",
    "https://docker.yomansunter.com",
    "https://aicarbon.xyz",
    "https://666860.xyz",
    "https://docker.zhai.cm",
    "https://a.ussh.net",
    "https://hub.littlediary.cn",
    "https://hub.rat.dev",
    "https://docker.m.daocloud.io"
  ]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

使用 DockerHub Proxy,以下以 hub.uuuadc.top 为例:可以根据列表自行替换来测试是否拉取成功

复制代码
docker pull hub.uuuadc.top/library/mysql:5.7

第一个docker进程

复制代码
# 拉取镜像并运行容器
[root@lb ~]# docker run -d -p 80:80 --name nginx_first docker.1ms.run/nginx
Unable to find image 'docker.1ms.run/nginx:latest' locally
latest: Pulling from nginx
8a628cdd7ccc: Pull complete
75b642592991: Pull complete
553c8756fd66: Pull complete
10fe6d2248e3: Pull complete
3b6e18ae4ce6: Pull complete
3dce86e3b082: Pull complete
e81a6b82cf64: Pull complete
Digest: sha256:09369da6b10306312cd908661320086bf87fbae1b6b0c49a1f50ba531fef2eab
Status: Downloaded newer image for docker.1ms.run/nginx:latest
4695455441b97f62953f9f1199ad51a55cb42074feebfa26b75433506f3488c8

# 查看容器
[root@lb ~]# docker ps -a
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                                 NAMES
4695455441b9   docker.1ms.run/nginx   "/docker-entrypoint...."   37 seconds ago   Up 36 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp   nginx_first

# curl访问测试
[root@lb ~]# curl localhost:80
<!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>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

第一个进程详解

运行下面的命令都发生了什么?

复制代码
docker run -d -p 80:80 --name nginx_first docker.1ms.run/nginx
  • docker run:这是 Docker 命令,用于创建并运行一个新的容器。
  • -d:指定容器后台运行
  • -p 80:80:这个参数用于映射端口。它将容器内部的 80 端口映射到宿主机的 80 端口。这意味着访问宿主机的 80 端口时,实际上是访问容器内部的 80 端口。
  • --name nginx_first:这个选项给新创建的容器指定一个名称,这里是 nginx_first。如果不指定名称,Docker 会自动生成一个名称。
  • docker.1ms.run/nginx:这是要运行的镜像的名称。这里使用的是 docker.1ms.run 作为镜像仓库地址,nginx 是镜像名称

执行这个命令后,Docker 会做以下几件事:

  • 检查本地是否有指定的 nginx 镜像。如果没有,Docker 会尝试从指定的镜像仓库(经过前缀替换后的地址)拉取镜像。
  • 如果镜像存在,Docker 会创建一个新的容器实例,并使用指定的配置(如端口映射和容器名称)。
  • 容器启动后,Docker 会在后台运行它,使得 Nginx 服务在宿主机的 80 端口上可用。

docker镜像管理

docker镜像核心指令

  • docker images (docker image ls):查看本机所有镜像
  • docker images -a:可以查看系统中所有镜像,包含隐藏镜像
  • docker search xxx :搜索镜像,优先选官方,start数量多
  • docker pull xxx:拉取镜像(下载镜像),注意版本
  • docker push xxx:推送镜像(上传镜像)
  • docker load xxx :导入镜像
  • docker save xxx :导出镜像
  • docker rmi xxx:删除镜像
  • docker tag xxx : 给镜像打标签
  • docker image prune :清理一些临时镜像-虚悬镜像
  • docker image inspect xxx:查看镜像的信息,输出的是json格式
  • docker image build xxx (docker build):构建镜像
  • docker commit 容器名 : 从更改过的容器创建一个新的 docker 镜像
  • docker image -f 过滤指令

docker pull使用

docker pull命令是用来下载镜像

复制代码
# 下载MySQL镜像,不指定版本号,默认下载最新的镜像
[root@lb ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
cea172a6e83b: Pull complete
daac2c594bdd: Pull complete
cb8acbf2440c: Pull complete
fae51f7de1fb: Pull complete
b2ead3e96e6b: Pull complete
769c3ac51f88: Pull complete
79f239a40e62: Pull complete
c11056354384: Pull complete
49978e7ccddf: Pull complete
548990e33276: Pull complete
Digest: sha256:0596fa224cdf3b3355ce3ddbfd7ce77be27ec9e51841dfc5d2e1c8b81eea69d2
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest

#查看镜像
[root@lb ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
docker.1ms.run/nginx   latest    4cad75abc83d   2 months ago   192MB
mysql                  latest    567107cb6971   2 months ago   797MB

# 下载MySQL5.7
[root@lb ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
20e4dcae4c69: Pull complete
1c56c3d4ce74: Pull complete
e9f03a1c24ce: Pull complete
68c3898c2015: Pull complete
6b95a940e7b6: Pull complete
90986bb8de6e: Pull complete
ae71319cb779: Pull complete
ffc89e9dfd88: Pull complete
43d05e938198: Pull complete
064b2d298fba: Pull complete
df9a4d85569b: Pull complete
Digest: sha256:4bc6bc963e6d8443453676cae56536f4b8156d78bae03c0145cbe47c2aad73bb
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

# 查看镜像
[root@lb ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
docker.1ms.run/nginx   latest    4cad75abc83d   2 months ago    192MB
mysql                  latest    567107cb6971   2 months ago    797MB
mysql                  5.7       5107333e08a8   16 months ago   501MB

docker pull使用注意事项

  • 下载镜像时如果不指定标签,则下载的是最新版本。
  • 下载指定版本:docker pull 服务名:版本号

docker savedocker load使用

docker save是将镜像保存到宿主机,而docker load是将宿主机中的镜像包导入到docker的镜像

示例:

复制代码
#导出镜像
[root@lb ~]# docker save mysql:5.7 -o /data/docker/images/mysql5.7.tar

[root@lb ~]# ll /data/docker/images/
total 507428
drwxr-xr-x 2 root root      4096 Apr 12 13:43 ./
drwxr-xr-x 3 root root      4096 Apr 12 13:42 ../
-rw------- 1 root root 519596032 Apr 12 13:43 mysql5.7.tar

# 删除所有镜像
[root@lb ~]# docker rmi $(docker images -q)

# 导入镜像
[root@lb ~]# docker load -i /data/docker/images/mysql5.7.tar
cff044e18624: Loading layer [==================================================>]    145MB/145MB
7ff7abf4911b: Loading layer [==================================================>]  11.26kB/11.26kB
8b2952eb02aa: Loading layer [==================================================>]  2.383MB/2.383MB
d76a5f910f6b: Loading layer [==================================================>]  13.91MB/13.91MB
8527ccd6bd85: Loading layer [==================================================>]  7.168kB/7.168kB
4555572a6bb2: Loading layer [==================================================>]  3.072kB/3.072kB
0d9e9a9ce9e4: Loading layer [==================================================>]  79.38MB/79.38MB
532b66f4569d: Loading layer [==================================================>]  3.072kB/3.072kB
337ec6bae222: Loading layer [==================================================>]  278.8MB/278.8MB
73cb62467b8f: Loading layer [==================================================>]  17.41kB/17.41kB
441e16cac4fe: Loading layer [==================================================>]  1.536kB/1.536kB
Loaded image: mysql:5.7

#查看镜像
[root@lb ~]# docker images | grep mysql
mysql                  5.7       5107333e08a8   16 months ago   501MB

docker inspect使用

docker inspect可以查看容器、镜像、网络、数据卷等资源的信息并输出json格式,这里我们使用它查看一下镜像的相关信息

使用jq命令加工输出的json格式

复制代码
apt install -y jq

示例:过滤MySQL中需要映射的端口

复制代码
[root@lb ~]# docker inspect mysql:5.7 | jq .[].Config.ExposedPorts
{
  "3306/tcp": {},
  "33060/tcp": {}
}