docker容器技术

由于开始学习最新1.24版本k8s,移除了docker,后续开始使用containerd

但是docker还是必须得会,依然是市场占有率最大,必须要会运维的技术产品。

docker文档

https://dockerdocs.cn/get-started/index.html

认识docker

介绍docker的前世今生,了解docker的实现原理,以包含Java、Django、前端等多个项目为例,带大家如何编写最佳的Dockerfile构建镜像。

通过本章的学习,大家会知道docker的概念及基本操作,并学会构建自己的业务镜像,并通过抓包的方式掌握Docker最常用的bridge网络模式的通信。

需要一种轻量、高效的虚拟化能力。

image-20230228162545253

Docker 公司位于旧金山,原名dotCloud,底层利用了Linux容器技术(LXC)(在操作系统中实现资源隔离与限制)。为了方便创建和管理这些容器,dotCloud 开发了一套内部工具,之后被命名为“Docker”。Docker就是这样诞生的。

Hypervisor: 一种运行在基础物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享硬件 。常见的VMware的 Workstation 、ESXi、微软的Hyper-V或者思杰的XenServer。

Container Runtime:通过Linux内核虚拟化能力管理多个容器,多个容器共享一套操作系统内核。

因此摘掉了内核占用的空间及运行所需要的耗时,使得容器极其轻量与快速。Docker是其中最知名的一种容器Container Runtime,其他的还有 CoreOS容器Rkt ,Podman。

image-20230228163749570

docker与devops

img-01

引入docker之后,软件交付的改革

容器火爆>云原生时代

云原生要素

  • 容器化
  • 微服务
  • 持续交付、devops
  • k8s(得益于Docker的大火)

微服务,拆分单体应用为多个子程序,以容器运行

面试题:容器与传统部署的区别

思考: 基于docker容器部署应用和虚拟机部署应用最大的区别?

简单总结:

  • 可以把应用程序代码及运行依赖环境打包成镜像(压缩文件),作为交付介质,在各环境部署
  • 可以将镜像(image)启动成为容器(container),并且提供多容器的生命周期进行管理(启、停、删)
  • container容器之间相互隔离,且每个容器可以设置资源限额
  • 提供轻量级虚拟化功能,容器就是在宿主机中的一个个的虚拟的空间,彼此相互隔离,完全独立

docker架构

基于操作系统内核,提供轻量级虚拟化功能的CS架构的软件产品。

img

docker版本

  • Docker 引擎主要有两个版本:企业版(EE)和社区版(CE)
  • 每个季度(1-3,4-6,7-9,10-12),企业版和社区版都会发布一个稳定版本(Stable)。社区版本会提供 4 个月的支持,而企业版本会提供 12 个月的支持
  • 每个月社区版还会通过 Edge 方式发布月度版
  • 从 2017 年第一季度开始,Docker 版本号遵循 YY.MM-xx 格式,类似于 Ubuntu 等项目。例如,2018 年 6 月第一次发布的社区版本为 18.06.0-ce

img

docker发展史

img

Docker 1.8之前,使用LXC,Docker在上层做了封装, 把LXC复杂的容器创建与使用方式简化为自己的一套命令体系。

LCX只能再linux平台创建容器

之后,为了实现跨平台等复杂的场景,Docker抽出了libcontainer项目,把对namespace、cgroup的操作封装在libcontainer项目里,支持不同的平台类型。

libcontainer实现了跨平台的容器创建。

2015年6月,Docker牵头成立了 OCI(Open Container Initiative开放容器计划)组织,这个组织的目的是建立起一个围绕容器的通用标准 。 容器格式标准是一种不受上层结构绑定的协议,即不限于某种特定操作系统、硬件、CPU架构、公有云等 , 允许任何人在遵循该标准的情况下开发应用容器技术,这使得容器技术有了一个更广阔的发展空间。

OCI成立后,libcontainer 交给OCI组织来维护,但是libcontainer中只包含了与kernel交互的库,因此基于libcontainer项目,后面又加入了一个CLI工具,并且项目改名为runC (https://github.com/opencontainers/runc ), 目前runC已经成为一个功能强大的runtime工具。

runC是最底层的工具,可以直接修改内核

Docker也做了架构调整。将容器运行时相关的程序从docker daemon剥离出来,形成了containerd。containerd向上为Docker Daemon提供了gRPC接口,使得Docker Daemon屏蔽下面的结构变化,确保原有接口向下兼容。向下通过containerd-shim结合runC,使得引擎可以独立升级,避免之前Docker Daemon升级会导致所有容器不可用的问题。

image-20230301135020965

也就是说

  • runC(libcontainer)是符合OCI标准的一个实现,与底层系统交互
  • containerd是实现了OCI之上的容器的高级功能,比如镜像管理、容器执行的调用等
  • Dockerd目前是最上层与CLI交互的进程,接收cli的请求并与containerd协作

小结

  1. 为了提供一种更加轻量的虚拟化技术,docker出现了
  2. 借助于docker容器的轻、快等特性,解决了软件交付过程中的环境依赖问题,使得docker得以快速发展
  3. Docker是一种CS架构的软件产品,可以把代码及依赖打包成镜像,作为交付介质,并且把镜像启动成为容器,提供容器生命周期的管理
  4. docker-ce,每季度发布stable版本。18.06,18.09,19.03
  5. 发展至今,docker已经通过制定OCI标准对最初的项目做了拆分,其中runC和containerd是docker的核心项目,理解docker整个请求的流程,对我们深入理解docker有很大的帮助

DevOps与云原生

  • 持续交付
  • 容器化
  • 微服务化

安装docker

宿主机网卡转发

## 若未配置,需要执行如下
$ cat <<EOF >  /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
EOF


$ sysctl -p /etc/sysctl.d/docker.conf

yum安装docker

## 下载阿里源repo文件
$ curl -o /etc/yum.repos.d/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
$ curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

$ yum clean all && yum makecache
## yum安装
$ yum install docker-ce-20.10.18 -y
## 查看源中可用版本
$ yum list docker-ce --showduplicates | sort -r
## 安装旧版本
##yum install -y docker-ce-18.09.9

## 配置源加速
## https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
#你可以自己去阿里云镜像仓库里,设置自己的加速器,或者用于超老师的这个也行。
# 阿里会去同步docker hub的镜像,同步到它自己的仓库
mkdir -p /etc/docker
cat >/etc/docker/daemon.json <<'EOF'
{
  "registry-mirrors" : [
    "https://ms9glx6x.mirror.aliyuncs.com"
  ]
}
EOF

## 设置开机自启
systemctl enable docker  
systemctl daemon-reload

## 启动docker
systemctl start docker 

## 查看docker信息
docker info
[root@es-node1 ~]#docker info |grep aliyun
https://ms9glx6x.mirror.aliyuncs.com/



## docker-client
which docker
## docker daemon
ps aux |grep docker
## containerd
ps aux|grep containerd
systemctl status containerd

安装软件包

Installed:
  docker-ce.x86_64 3:20.10.18-3.el7                                                                                    
Dependency Installed:
  containerd.io.x86_64 0:1.6.18-3.1.el7                    docker-buildx-plugin.x86_64 0:0.10.2-1.el7                  
  docker-ce-cli.x86_64 1:23.0.1-1.el7                      docker-ce-rootless-extras.x86_64 0:23.0.1-1.el7             
  docker-compose-plugin.x86_64 0:2.16.0-1.el7              docker-scan-plugin.x86_64 0:0.23.0-3.el7 

很明显,安装docker-ce,底层自动装了containerd去管理底层容器

docker服务端查询

[root@es-node1 ~]#docker version
Client: Docker Engine - Community
 Version:           23.0.1
 API version:       1.41 (downgraded from 1.42)
 Go version:        go1.19.5
 Git commit:        a5ee5b1
 Built:             Thu Feb  9 19:51:00 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          20.10.18
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.6
  Git commit:       e42327a
  Built:            Thu Sep  8 23:12:21 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.18
  GitCommit:        2456e983eb9e37e47538f59ea18f2043c9a73640
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

可见,docker服务端是我们目前在用的,后期k8s去掉了docker这一层,直接使用containerd管理容器。

容器核心实践

图解

image-20230301174244849

三大核心要素:镜像(Image)、容器(Container)、仓库(Registry)

镜像Image

打包了业务代码及运行环境的包,是静态的文件,不能直接对外提供服务。

容器Container

镜像的运行时,可以对外提供服务。

仓库Registry

存放镜像的地方

  • 公有仓库,Docker Hub,阿里,网易...
  • 私有仓库,企业内部搭建
    • Docker Registry,Docker官方提供的镜像仓库存储服务
    • Harbor, 是Docker Registry的更高级封装,它除了提供友好的Web UI界面,角色和用户权限管理,用户操作审计等功能
  • 镜像访问地址形式 registry.devops.com/demo/hello:latest,若没有前面的url地址,则默认寻找Docker Hub中的镜像,若没有tag标签,则使用latest作为标签。 比如,docker pull nginx,会被解析成docker.io/library/nginx:latest
  • 公有的仓库中,一般存在这么几类镜像
    • 操作系统基础镜像(centos,ubuntu,suse,alpine)
    • 中间件(nginx,redis,mysql,tomcat)
    • 语言编译环境(python,java,golang)
    • 业务镜像(django-demo...)

容器和仓库不会直接交互,都是以镜像为载体来操作。

镜像管理

1.查看镜像列表
docker images

2.获取镜像,不加tag是最新版本
# 完整的镜像地址是 https://image-repo.yuchaoit.cn/nginx:alpine 以此确认唯一地址

docker pull nginx:alpine
docker pull ubuntu
# 等于
docker pull ubuntu:latest


3.使用tag获取制定版本
docker pull centos:7

# 生产下更多用debian、alpine作为base image
# bug少,体积少,安全性高,可以运行业务
docker pull nginx:alpine

4.修改tag,如后续推送镜像到镜像仓库,需要改tag
[root@es-node1 ~]#docker tag eeb6ee3f44bd yuchao163/centos:7
[root@es-node1 ~]#docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
centos             7         eeb6ee3f44bd   17 months ago   204MB
yuchao163/centos   7         eeb6ee3f44bd   17 months ago   204MB

tag等于一个软连接,指向同一个镜像

5.搜索镜像,默认去docker hub搜索镜像
# https://hub.docker.com/
[root@es-node1 ~]#docker search nginx

6.不同镜像,制作的体积大小不一
[root@es-node1 ~]#docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
nginx              alpine    cc44224bfe20   14 months ago   23.5MB
nginx              latest    605c77e624dd   14 months ago   141MB
centos             7         eeb6ee3f44bd   17 months ago   204MB
yuchao163/centos   7         eeb6ee3f44bd   17 months ago   204MB

查询镜像tag(技巧)

走官网api更方便

[root@es-node1 ~]#cat /usr/bin/dockertag.sh 
curl -L -s "https://registry.hub.docker.com/v2/repositories/library/$1/tags?page_size=1024" | jq '.results[]["name"]' | sed 's/\"//g' | sort -u
[root@es-node1 ~]#
[root@es-node1 ~]#
[root@es-node1 ~]#dockertag.sh image-name

容器管理

# 运行容器,里面运行nginx程序
[root@es-node1 ~]#docker run -d --name my-nginx01 nginx:alpine
a4e7c7e86b95513eb9e82824caa9adf2b6d994e8b019653fea839e7108d73bcc
[root@es-node1 ~]#
[root@es-node1 ~]#

# 查看容器进程
[root@es-node1 ~]#docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
a4e7c7e86b95   nginx:alpine   "/docker-entrypoint.…"   3 seconds ago   Up 2 seconds   80/tcp    my-nginx01
[root@es-node1 ~]#

# 查看容器信息、ip
[root@es-node1 ~]#docker inspect my-nginx01 |grep -i 'ipaddress'
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

# 访问容器应用
[root@es-node1 ~]#curl 172.17.0.2 -I
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Wed, 01 Mar 2023 07:37:43 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 18:48:00 GMT
Connection: keep-alive
ETag: "61cb5be0-267"
Accept-Ranges: bytes

[root@es-node1 ~]#

# 进入容器内,查看nginx信息
[root@es-node1 ~]#docker exec -it my-nginx01 sh
/ # ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 nginx: master process nginx -g daemon off;
   32 nginx     0:00 nginx: worker process
   33 nginx     0:00 nginx: worker process
   34 nginx     0:00 nginx: worker process
   35 nginx     0:00 nginx: worker process
   54 root      0:00 sh
   60 root      0:00 ps -ef
/ #

容器是怎么定义运行的?

[root@es-node1 ~]#docker images nginx:alpine
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        alpine    cc44224bfe20   14 months ago   23.5MB

为什么你docker run这个镜像,就可以运行一个容器,里面还有nginx?
这是由镜像的构建本质而来

[root@es-node1 ~]#docker history nginx:alpine
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
cc44224bfe20   14 months ago   /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B

手工安装ubuntu-nginx

docker run -it --name ubuntu-nginx-test ubuntu
# 部署操作
sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

apt-get update && apt install -y nginx
nginx -g 'daemon off;'

# 客户端访问测试ubuntu下的nginx

自建镜像dockerfile

理解镜像是如何运行为容器,以及定义的逻辑

# 告诉docker使用哪个基础镜像作为模板,后续命令都以这个镜像为基础 
FROM ubuntu

# 替换源
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

# RUN命令会在上面指定的镜像里执行命令 
RUN apt-get update && apt install -y nginx

#告诉docker,启动容器时执行如下命令
CMD ["/usr/sbin/nginx", "-g","daemon off;"]

构建脚本,生成镜像

[root@es-node1 ~]#mkdir devops-docker
[root@es-node1 ~]#cd devops-docker/
[root@es-node1 ~/devops-docker]#vim Dockerfile
[root@es-node1 ~/devops-docker]#docker build . -t my-nginx-ubuntu:v1 -f Dockerfile

[root@es-node1 ~/devops-docker]#docker images my-nginx-ubuntu
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-nginx-ubuntu   v1        d7ac2c2be87e   10 seconds ago   173MB

使用新镜像,运行新容器,注意镜像名字写完整了,否则找不到

[root@es-node1 ~/devops-docker]#docker run -d --name nginx02  my-nginx-ubuntu:v1 
ba38541c077a394eefb748e9516daf078e3eb1d85bb80bcd0feb68f4bf1bc426

图解容器创建过程

多见识原理,逻辑等,便于排查深度的问题。

image-20230301163829105

流程图

image-20230301173253491

容器是提供一个运行环境,以及保存你的程序运行后,产生的数据。

后续我们继续练习,用docker部署python、java等项目加深理解。

image-20230301174010265

访问容器内http程序

# 删掉旧服务,重新启动
$ docker rm -f my-nginx-alpine
$ docker run --name my-nginx-alpine -d -p 18080:80 nginx:alpine
# 访问宿主机18080端口
[root@es-node1 ~]#curl http://10.0.0.18:18080/

portainer可视化管理docker

https://www.portainer.io/

通过本地socket文件,连接上docker服务端,获取docker所有信息

支持功能

  • 镜像,容器信息查看,inspece
  • 远程管理,exec
  • 日志,logs

复杂容器管理用k8s、也有些小公司生产下用portainer。

# ip:port 方式一
# /var/run/docker.sock  方式二
[root@es-node1 ~]#ls /var/run/docker.sock  -l
srw-rw---- 1 root docker 0 Mar  1 14:21 /var/run/docker.sock


# 一个展示docker进程信息的程序
$ docker run --name portainer -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
#注册
admin
admin123

image-20230301175941194

导出镜像

导出镜像,发给你的同事

[root@es-node1 ~]#docker save -o /tmp/nginx-alpine.tar nginx:alpine
[root@es-node1 ~]#file /tmp/nginx-alpine.tar 
/tmp/nginx-alpine.tar: POSIX tar archive

导入镜像

从压缩文件,导入镜像到docker里,你同事怎么接受,使用你的镜像

docker load -i nginx-alpine.tar

删除镜像/容器

# 删除容器
[root@es-node1 ~]#
[root@es-node1 ~]#docker stop my-nginx-alpine
my-nginx-alpine
[root@es-node1 ~]#docker rm my-nginx-alpine
my-nginx-alpine


# 删除镜像,注意,名字上的完整性
[root@es-node1 ~]#docker rmi nginx:alpine

限制容器资源使用

## 后台启动
$ docker run --name nginx -d nginx:alpine

## 映射端口,把容器的端口映射到宿主机中,-p <host_port>:<container_port>
$ docker run --name nginx -d -p 8080:80 nginx:alpine

## 资源限制,最大可用内存500M
$ docker run --memory=500m nginx:alpine

容器数据持久化

运行容器后,希望数据持久化存储,如mysql的/var/lib/mysql

## 挂载主机目录
$ docker run --name nginx -d  -v /opt:/opt  nginx:alpine

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456  -d -v /tmp/mysql/:/var/lib/mysql mysql:5.7

# 测试数据持久化,容器修改、删除后,宿主机数据保留了
[root@es-node1 ~]#docker exec -it mysql bash

mysql> create database yuchaoit;
Query OK, 1 row affected (0.00 sec)

[root@es-node1 ~]#docker rm `docker stop mysql`

# 宿主机保留了mysql数据
[root@es-node1 ~]#ls /tmp/mysql/

进入容器

# 1.进入容器且运行sh解释器
$ docker exec -ti <container_id_or_name> /bin/sh

# 2.不进入容器,不开终端,直接在容器内执行xx命令
$ docker exec <container_id_or_name> hostname

拷贝容器数据

# 拿出容器内的文件
[root@es-node1 ~]#docker cp mysql:/etc/hosts /tmp/mysql_hosts


# 放文件进入容器
[root@es-node1 ~]#docker cp init.sh mysql:/tmp/
Preparing to copy...
Copying to container - 2.56kB
Successfully copied 2.56kB to mysql:/tmp/
[root@es-node1 ~]#
[root@es-node1 ~]#docker exec mysql ls /tmp
init.sh

查看容器/镜像信息

## 查看容器详细信息,包括容器IP地址等
$ docker inspect nginx

## 查看镜像的明细信息
$ docker inspect nginx:alpine

查看容器运行日志

[root@es-node1 ~]#docker logs -f mysql

[root@es-node1 ~]#docker logs -f --tail=10 mysql

小结

image-20230301180815176

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2024-03-31 19:22:46

results matching ""

    No results matching ""