1. Docker 概述
Docker是一个开源的容器平台,它允许开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中。
1.1. 什么是Docker?
Docker是一个开源的容器平台,它允许开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中。这使得应用程序可以在不同的环境中一致地运行,无论是开发、测试还是生产环境。
Docker的主要优势在于它提供了一种简化的方法来创建、部署和运行应用程序,同时确保应用程序在各种环境中的一致性。这有助于减少因环境差异导致的问题,提高了开发和部署的效率。Docker还可以与其他工具和平台(如Kubernetes)集成,以实现更高级的容器编排和管理功能。
1.2. Docker的工作原理是什么?
Docker的工作原理主要基于容器技术。容器是一种轻量级的虚拟化技术,它允许在同一台主机上运行多个隔离的应用程序实例。与传统的虚拟机技术相比,容器共享主机操作系统内核,因此它们更加轻量、快速且高效。下面是Docker的一些关键组件和它们的工作原理:
1.2.1. Docker镜像
Docker镜像是一个只读的模板,包含了运行容器所需的文件系统、应用程序和依赖项。镜像可以从Docker Hub(一个公共的镜像仓库)获取,也可以从私有仓库获取,或者通过Dockerfile自定义创建。
1.2.2. Docker容器
容器是Docker镜像的运行实例。当你启动一个容器时,Docker会在镜像的基础上创建一个可写层,这样容器内的应用程序可以在运行时读写数据。每个容器都是相互隔离的,拥有自己的文件系统、网络接口和进程空间。
1.2.3. Docker守护进程(Docker Daemon)
Docker守护进程是一个后台进程,负责管理Docker容器的生命周期,包括创建、启动、停止和删除容器。守护进程还负责与Docker镜像仓库通信,以获取和推送镜像。
1.2.4. Docker客户端(Docker Client)
Docker客户端是一个命令行工具,用于与Docker守护进程进行通信。用户可以通过Docker客户端执行各种操作,如创建、启动、停止容器,以及管理镜像等。
1.2.5. Dockerfile
Dockerfile是一个文本文件,包含了一系列指令,用于描述如何从基础镜像构建一个新的Docker镜像。Dockerfile可以包括添加文件、安装软件包、设置环境变量等操作。
1.2.6. Docker网络
Docker提供了一套网络功能,允许容器之间以及容器与主机之间进行通信。Docker支持多种网络模式,如桥接、主机和覆盖网络等,以满足不同场景的需求。
1.3. Docker的优势有哪些?
1.3.1. 快速部署
短时间内可以部署成百上千个应用, 更快速交付到线上
1.3.2. 高效虚拟化
不需要为hypervisor支持, 基于Linux内核实现应用虚拟机, 相比虚拟机大幅提高性能和效率
1.3.3. 节省开支
提高服务器利用率, 降低IT支持
1.3.4. 简化配置
将运行环境打包保存至容器, 使用时直接启动即可
1.3.5. 环境统一
将开发, 测试, 生成的应用运行环境进行标准化和统一, 减少环境不一样带来的各种问题
1.3.6. 快速迁移和扩展
可实现跨平台运行在物理机, 虚拟机, 公有云等环境, 良好的兼容性可以方便将应用从A宿主机迁移到B宿主机, 甚至是A平台迁移到B平台
1.3.7. 更好的实现 面向服务的架构
一个容器只运行一个应用, 实现分布的应用模型, 可以方便的进行横向扩展, 符合开发中高内聚, 低耦合的要求, 减少不同服务之间的相互影响
2. Docker 安装(略)
3. Docker 使用
3.1. 服务
3.1.1. 查看Docker版本信息
$ docker version
3.1.2. 查看docker简要信息
$ docker -v
3.1.3. 启动Docker
$ systemctl start docker
3.1.4. 关闭docker
$ systemctl stop docker
注:警告的含义是尽管你已经停止了 docker 服务,但通过 docker.socket,仍然可以重新激活 docker 服务。这可能是出于一些自动化或恢复性的考虑,使得在需要时能够快速启动 docker 服务。
3.1.5. 设置开机启动
$ systemctl enable docker
3.1.6. 重启docker服务
$ service docker restart
3.1.7. 关闭docker服务
$ service docker stop
$ systemctl stop docker.socket
3.2. 镜像
3.2.1. 检索镜像
$ docker search 关键字
3.2.2. 拉取镜像
$ docker pull 镜像名称:版本号
3.2.3. 列出镜像
$ docker image ls
$ docker images
3.2.4. 删除镜像
删除指定镜像
$ docker rmi <镜像Id>
3.2.5. 导出镜像
将镜像保存为归档文件
$ docker save image_name -o file_path
3.2.6. 导入镜像
$ docker load -i file_path
3.2.7. Dockerfile构建镜像(演示在 9.镜像运行 下方)
Dockerfile 是一个文本格式的配 文件,用户可以使用 Dockerfile 来快速创建自定义的镜像。
Dockerfile 由一行行行命令语句组成,并且支持以#开头的注释行.
● FROM:指定基础镜像
● RUN:执行命令
● COPY:复制文件
● ADD:更高级的复制文件
● CMD:容器启动命令
● ENV:设置环境变量
● EXPOSE:暴露端口
其它的指令还有ENTRYPOINT、ARG、VOLUME、WORKDIR、USER、HEALTHCHECK、ONBUILD、LABEL等等。
例如(创建一个具有Vim功能的ubuntu容器):
# 指定基础镜像
FROM ubuntu:latest
# 安装 Vim 和其他必要的软件包
RUN apt-get update && \
apt-get install -y vim
# 定义容器启动时执行的命令
CMD ["vim"]
3.2.8. 镜像构建(演示在 9.镜像运行 下方)
$ docker build
3.2.9. 镜像运行
镜像运行,就是新建并运行一个容器。
$ docker run
3.3. 容器
3.3.1. 查看容器列表
$ docker ps
3.3.2. 生成docker容器
$ docker run [OPTIONS] image [COMMAND]
OPTINONS:
--name="新名字"
-d :后台运行
-d:后台运行
-i:交互模式运行模式
-t:伪终端
-P:随机端口映射,大写P
-p:指定端口映射,小写p
例如:
3.3.3. 挂载(进入)到正在运行的容器中
$ docker attach [CONTAINER ID]
3.3.4. 删除容器
$ docker rm [CONTAINER ID] #删除容器
$ docker rm $(docker ps -a -q) #删除所有容器
3.3.5. 启动一个容器
$ docker start 容器ID或容器名 #启动容器
$ docker restart 容器ID或容器名 #重启容器
3.3.6. 停止一个容器
$ docker stop 容器ID或容器名 #停止容器
$ docker kill 容器ID或容器名 #强制停止容器
3.3.7. 提交
$ docker commit id -learn/ping #刚才修改的镜像进行提交,即提交新的镜像,ping是新的镜像名
3.3.8. 进入容器
$ docker exec -it 容器名或容器ID 启动方式
3.3.9. 暂停启动的容器
# 暂停正在运行的镜像容器,用途是在启动的容器的过程有的容器启动快了,有的还没有就绪,一般调试时使用
$ docker pause 容器ID或容器名
# 解除暂停
$ docker unpause 容器ID或容器名
3.3.10. 更新一个或多个容器的配置
$ docker update [OPTIONS] CONTAINER [CONTAINER...]
--blkio-weight #阻塞Io(相对权重),介于10到1000之间,0表示禁用(默认禁止)
--cpu-period #限制CPU CFS(完全公平的调度程序)期限
--cpu-quota #限制CPU CFS(完全公平的调度程序)配额
--cpu-rt-period # API 1.25+,将CPU实时时间限制为微秒
--cpu-rt-runtime # API 1.25+,将CPU实时运行时间限制为微秒
--cpu-shares,-c#CPU份额(相对权重)
--cpus #API 1.29+,CPu数量
--cpuset-cpus #允许执行的CPU (0-3,0,1)
--cpuset-mem #允许执行的MEM(0-3,0,1)
--kernel-memory #内核内存限制
--memory-swap #交换限制等于内存加交换,“-1”以启用无限交换
--memory-reservatio #内存软限制
--memory, -m#内存限制
--pids-limit #API 1.40+,调节容器pids限制(-1表示无限制)
--restart #容器退出时重新启动策略以应用
3.3.11. 退出容器
exit #退出容器
3.3.12. 从容器文件拷贝
docker 容器ID:容器内路径 目的主机路径
3.3.13. 容器导入导出
# 导出容器命令格式
$docker export容器ID>文件名.tar
# 导入成新的镜像
$ cat 文件名.tar | docker import -镜像用户/镜像名:镜像版本号
3.4. 日志
3.4.1. 查看日志
$ docker logs [容器ID]
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志
3.5. 容器卷(数据卷)
3.5.1. 容器卷是什么?
- 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据特性
- 卷的设计目的就是数据持久化,完全独立于容器的生存周期,因此docker不会在容器删除时删除其挂载的数据卷
- 一句话:类似于redis里面的rdb和aof 文件
- 将docker容器内容的数据保存进宿主机的磁盘中
- 运行一个带有容器卷存储功能的容器实例
3.5.2. 容器卷能干嘛?
- 突然容器挂了或者被删除了,容器内目录数据会自动保存到宿主机绝对目录中
- 将运用于运行的环境打包镜像,run后形成容器实例运行,但是我们对数据的要求希望是持久化的
3.5.3. 数据卷的特点:
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
3.5.4. 案例
运行容器,指定挂载数据卷命令:
$ docker run -it -v 主机目录:容器目录
具体代码:
$ docker pull mongo #拉取mongo命令
$ docker run -d -p 27017:27017 -v /var/mongodb:/data/db --name mongodb mongo #创建容器并添加挂载信息
$ docker inspect mongodb #查看挂载信息
3.6. 向镜像仓库推送镜像
3.6.1. 首先登录
$ docker login
# 会提示你输入账号密码,不在演示
3.6.2. 使用附加标签标注镜像
$ docker tag 镜像名 名字/镜像名
3.6.3. Push到远程仓库
$ docker push 名字/镜像名
4. Docker使用案例
4.1. 安装单机Tomcat
4.1.1. 查询镜像
# 首先查询镜像
$ docker search tomcat
4.1.2. 下载镜像
$ docker pull tomcat
4.1.3. 安装启动tomcat
$ docker run -d -p 8080:8080 --name tomcat tomcat
这个时候访问8080端口会发现页面是404,这是因为tomcat默认空目录,需要修改目录
4.1.4. 修改目录
$ docker exec -it tomcat /bin/bash
$ ls
$ rm -r webapps
$ mv webapps.dist/ webapps
# 然后浏览器访问就发现可以正常访问了
4.2. 安装单机Nginx(不推荐)
4.2.1. 查询镜像
# 首先查询镜像
$ docker search nginx
4.2.2. 下载镜像
$ docker pull nginx #这里就用最新版本
4.2.3. 创建Nginx配置文件
启动前需要先创建Nginx外部挂载的配置文件( /home/nginx/conf/nginx.conf)
之所以要先创建 , 是因为Nginx本身容器只存在/etc/nginx 目录 , 本身就不创建 nginx.conf 文件
当服务器和容器都不存在 nginx.conf 文件时, 执行启动命令的时候 docker会将nginx.conf 作为目录创建 , 这并不是我们想要的结果 。
# 创建挂载目录
$ mkdir -p /home/nginx/conf
$ mkdir -p /home/nginx/log
$ mkdir -p /home/nginx/html
容器中的nginx.conf文件和conf.d文件夹复制到宿主机
# 生成容器
$ docker run --name nginx -p 9001:80 -d nginx
# 将容器nginx.conf文件复制到宿主机
$ docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
# 将容器conf.d文件夹下内容复制到宿主机
$ docker cp nginx:/etc/nginx/conf.d /home/nginx/conf/conf.d
# 将容器中的html文件夹复制到宿主机
$ docker cp nginx:/usr/share/nginx/html /home/nginx/
4.2.4. 创建Nginx容器并运行
Docker 创建Nginx容器
# 直接执行docker rm nginx或者以容器id方式关闭容器
# 找到nginx对应的容器id
$ docker ps -a
# 关闭该容器
$ docker stop nginx
# 删除该容器
$ docker rm nginx
# 或者之间 删除正在运行的nginx容器
$ docker rm -f nginx
重新创建容器
$ docker run -p 80:80 --name nginx -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/nginx/conf/conf.d:/etc/nginx/conf.d -v /home/nginx/log:/var/log/nginx -v /home/nginx/html:/usr/share/nginx/html -d nginx:latest
# -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf 挂载nginx.conf配置文件
# -v /home/nginx/conf/conf.d:/etc/nginx/conf.d 挂载nginx配置文件
# -v /home/nginx/log:/var/log/nginx 挂载nginx日志文件
# -v /home/nginx/html:/usr/share/nginx/html 挂载nginx内容
4.2.5. 修改首页
上面我们挂载了/home/nginx/html地址,修改即可
$ cd /home/nginx/html
$ vim index.html
# 修改保存之后,重启服务
$ docker restart nginx
4.3. 使用Dockerfile安装单机Nginx(推荐)
4.3.1. 前置准备
# 创建Dockerfile文件
$ vim Dockerfile
具体复制下面的Dockerfile内容:
# 使用官方的 Nginx 镜像作为基础镜像
FROM nginx
# 将自定义的 index.html 文件复制到容器中
COPY index.html /usr/share/nginx/html
# 可选:如果需要修改默认的 Nginx 配置,将自定义配置文件复制到容器中
# COPY nginx.conf /etc/nginx/nginx.conf
# 可选:如果需要开放额外的端口,例如 8080
EXPOSE 80
同级目录下,创建需要替换的index.html文件
$ vim index.html
# 这里只往里面添加了Hello,world,不在展示
4.3.2. 使用build命令,构建镜像:
$ docker build -t my-nginx-image .
# 名称为my-nginx-image
4.3.3. 之后创建容器即可。
$docker run -d -p 80:80 -v /home/nginx/index.html:/usr/share/nginx/html/index.html my-nginx-image
# /home/nginx/index.html 替换成你的index.html的具体路径
之后打开80端口查看访问成功:
4.4. 安装redis分布式集群
详见另一篇文章:手撕Redis-3主3从集群 - 掘金 (juejin.cn)
5. Docker网络
5.1. 三种默认的网络模式
分别是:bridge、host、none
除此之外还可以自定义网络模式
$ docker network ls
查看网桥信息(以bridge为例)
$ docker network inspect bridge
5.2. 基本命令
5.2.1. 查看网络
5.1有示例,这里不做演示
$ docker network ls [OPTIONS]
-f
--filter filter 过滤条件(如 'driver=bridge’)
--format string
--no-trunc
-q
--quiet 格式化打印结果 不缩略显示 只显示网络对象的ID
5.2.2. 创建新的网络对象
$ docker network create [OPTIONS] NETWORK
# 常用参数
--driver string 指定网络的驱动(默认 "bridge")
--subnet strings 指定子网网段(如192.168.0.0/16、172.88.0.0/24)
--ip-range strings 执行容器的IP范围,格式同subnet参数
--gateway strings 子网的IPv4 or IPv6网关,如(192.168.0.1)
5.2.3. 删除一个或多个网络
$ docker network rm NETWORK [NETWORK...]
#删除未使用的docker网络
$ docker network prune
5.2.4. 查看一个或多个网络的详细信息
5.1有示例,这里不做演示
$ docker network connect [OPTIONS] NETWORK CONTAINER
$ docker network disconnect [OPTIONS] NETWORK CONTAINER
5.2.5. 容器连接或断开到指定的 Docker 网络
将容器连接到指定的 Docker 网络
# 准备工作
$ docker network create testnetwork
$ docker run -d -it -p 9999:9999 --name ubuntu ubuntu
# 将 `<network-name>` 替换为目标网络的名称,`<container-id>` 替换为要连接到该网络的容器的 ID。
$ docker network connect <network-name> <container-id>
示例:
$ docker network connect testnetwork ubuntu
# 查看连接信息
docker network inspect testnetwork
断开容器与指定的 Docker 网络的连接
$ docker network disconnect <network-name> <container-id>
将 `<network-name>` 替换为目标网络的名称,`<container-id>` 替换为要断开连接的容器的 ID。
示例:
$ docker network disconnect testnetwork ubuntu
# 查看连接信息
docker network inspect testnetwork
#不再做演示,直接敲代码即可
5.3. 外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。
当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
当使用 docker ps -a 我们可以看到主机的80端口映射到了docker的80端口上:
上面讲容器的时候也提到过端口映射,可以映射到指定地址的任意端口和映射到指定地址的指定端口
这里不再解释
5.4. 容器互联(官网不推荐)
使用 --link 参数可以让容器之间安全的进行交互。
下面先创建一个新的数据库容器。
$ sudo docker run -d --name mysql mysql
然后创建一个新的 DB 容器,并将它连接到 mysql 容器
$ docker run -d --name mysql-container -e MYSQL_ROOT_PASSWORD=root mysql
$ docker run -d --name mysql-two-container -e MYSQL_ROOT_PASSWORD=root --link mysql-container:mysql mysql
5.5. 自定义网络(network)
使用 Alpine 镜像(很小只有5MB左右,直接pull下载即可)作为示例时,可以按照以下步骤创建一个自定义网络,并在两个 Alpine 容器之间进行通信
5.5.1. 创建一个自定义网络
$ docker network create mynetwork
# 创建一个名为mynetwork的自定义网络
5.5.2. 启动第一个 Alpine 容器,并将其连接到 "mynetwork" 网络
$ docker run -d -it --name alpine1 --network mynetwork alpine sh
# 这将创建一个名为 "alpine1" 的容器,并将其连接到 "mynetwork" 网络。
5.5.3. 启动第二个 Alpine 容器,并将其连接到相同的网络
$ docker run -d -it --name alpine2 --network mynetwork alpine sh
# 这将创建一个名为 "alpine2" 的容器,并将其连接到 "mynetwork" 网络。
5.5.4. 进行通信(示例)
进入 "alpine1" 容器的命令行终端
$ docker exec -it alpine1 sh
在 "alpine1" 容器中,使用 ping 命令来访问 "alpine2" 容器
$ ping alpine2
成功!
6. 结尾
这是之前学习Docker时做的笔记,今天重新整理以文档的方式产出,希望对看文章的你有所帮助~
日常分享学习中的教程,都看到这里了,点个赞再走吧~