百度解释:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
个人理解:将全部代码及其依赖的包和环境封装起来,使用宿主机的操作系统内核让代码运行在一个虚拟的机器中,只不过相较于虚拟机而言不用模拟操作系统,就用宿主机系统内核,更节省资源也更快启动
一致性(可移植性):只要能跑docker镜像,其他什么都不用装,拿过来用就完了,要什么里面都装好了。开发、测试、运行环境都完全一致。
沙箱机制:每个容器都是运行在封闭隔离的环境里,不对外提供任何接口,除了共享操作系统内核也不接受任何外部资源,相当安全;疑问:容器之间共享宿主机的系统内核,能不能通过对内核操作来破坏隔离
安装
配置yum源
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
配置镜像加速
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": []
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
安装
# 安装最新版
yum install -y docker-ce
# 安装指定版本
yum install -y docker-ce-2x.x.x
启动
开机启动
systemctl enable docker
启动
systemctl start docker
systemctl restart docker
停止docker
systemctl stop docker
关闭开机自动启动
systemctl disable docker
宿主机网卡转发
镜像收到请求时端口映射,将请求转发给相应的容器进行处理
cat <<EOF > /etc/sysct1.d/docker.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_forward=1
EOF
sysctl -p /etc/sysct1.d/docker.conf
基本操作
# 查看docker版本
docker version
# 查看docker信息
docker info
# 查看镜像
docker images
# 从仓库中搜索ubuntu镜像
docker search ubuntu# 下载镜像
docker pull ubuntu
# 指定版本
docker pull ubuntu:18.04
部署Flask项目
1、获取基础镜像
docker pull ubuntu:18.04
2、构建自定义镜像
2-1、Dockerfile
# Base images 选定基础镜像
FROM ubuntu:18.04
#MAINTAINER 维护者信息,自定义镜像的作者
MAINTAINER xiaohuo@foxmail.com
# RUN 安装软件包
RUN apt update # 用于更新APT包管理器的软件包列表,确保正在安装的软件包是最新的
RUN apt install python3 python3-pip -y
RUN pip3 install flask
RUN mkdir -p /data/www/
# 拷贝文件至工作目录,
COPY app.py /data/www/app.py
# 更改容器工作目录,后续Dockerfile 指令默认在此目录下执行
WORKDIR /data/www/
# 容器启动时执行命令
CMD ["python3", "app.py"] # 通过cmd 用"python3"执行"app.py"
优化
RUN apt update && \
apt install -y python3 python3-pip && \
rm -rf /var/lib/apt/lists/* && \
pip3 install flask && \
mkdir -p /data/www/ && \
<!--
"rm -rf /var/lib/apt/lists/*" 删除APT包管理器的软件包列表缓存,可以减少镜像大小和构建时间,还可以删除过时或者不安全的包以提高安全性
-->
2-2、app.py
from flask import Flask
app = Flask(__name__)
@app.route("/index")
def index():
return "hello world"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
2-3 命令构建自定义镜像
在构建过程中,Docker 会按照 Dockerfile 中的指令来执行一系列操作,比如安装软件包、复制文件等,最终生成一个新的 Docker 镜像
docer build -t xiaohuo:0.1 . -f Dockerfile
<!--"docker build" 构建镜像命令
"-t xiaohuo:0.1" t表示tag 用于给构建的镜像指定一个名字xiaohou和版本号0.1" . -f Dockerfile" 点表示当前目录 查找Dockerfile文件进行构建镜像,不指定文件默认路径下的Dockerfile文件
命令会告诉 Docker 从当前目录开始构建,使用 Dockerfile 作为构建脚本,并将构建的镜像命名为xiaohuo,版本标签为 0.1
-->
3、基于镜像创建容器并运行
docker run -d -p 80:8000 xiaohuo:0.1
<!--
"docker run" 用于从镜像启动一个新的容器实例。
"-d" 保证前台进程不主动退出的情况下后台运行容器
"-p 80:8000" 设置端口映射参数。-p 标志用于将宿主机的端口映射到容器内部的端口。宿主机的80端口被映射到了容器的8000端口。当有请求通过80端口访问时,请求会被转发到容器的8000端口,
"xiaohuo:0.1" Docker镜像的名称和标签
当有请求通过宿主机ip+80端口访问时,会被转发到端口号为8000的app.py中并运行对应的flask程序
-->
3-1 docker的基本命令
# 查看正在运行的容器
docker ps
# 查看所有容器,包括正在运行和已停止的
docker ps -a
# 停止运行容器,通过唯一标识符CONTAINER ID停止容器,此时仍可以通过docker ps -a查看所有容器,只不过状态是Exiteddocker stop 容器ID
# 删除容器
docker rm 容器ID# 删除镜像
docker rmi
# 查看容器日志docker logs ID
# 管道符查看最后5条日志
docker logs ID | tail -5# 进入正在运行容器的内部
docker exec -it ID bash
# 打包容器为新镜像
docker commit ID 镜像名
4、其他
4-1、缓存
缓存是Docker为了提高构建效率而引入的一个特性。当Dockerfile中的指令没有发生变化时,Docker会使用之前构建的缓存层来加速镜像的构建过程。
不禁用缓存构建镜像会使用之前的缓存层提高构建速度
不禁用缓存构建镜像
禁用缓存层会重新执行Dockerfile中每一条指令
docer build -t xiaohuo:0.1 . -f Dockerfile --no-cache
禁用缓存
4-2、对不含前台进程的镜像,创建容器并启动
docker run -ti ubuntu:18.04 bash
对于不含前台进程的镜像,在启动容器时启动一个bash shell编辑器当做前台进程,只要不退出bash,容器就不会停止;也可以使用ping 等命令作为前台进程保持容器的运行状态
Dockerfile基本操作
Dockerfile通常包括以下几个部分:
- 基础镜像:指定一个已经存在的镜像作为基础,然后在这个基础上进行构建。
# FROM 指定基础镜像,必须为第一个指令
FROM ubuntu:18.04
- 维护者信息:用于指定镜像的维护者信息,包括姓名和邮箱等。
MAINTAINER xiaohuo <xiaohuo@foxmail.com>
- 环境变量:设置环境变量,这些环境变量可以在后续的指令中使用。
ENV <key> <value>
# 定义
ENV v1p /data/www
# 使用
RUN mkdir -p $v1p/
- 工作目录:指定容器启动后的工作目录。后续Dockerfile指令在没有绝对路径的情况下默认在工作目录下执行
WORKDIR /data/www/
- 复制文件:将本地的文件或目录复制到容器的指定路径下。
# COPY | ADD 添加宿主机文件到镜像中
ADD home* /mydir/ # 添加所有开头为home的文件到根目录下的/mydir/ADD demo mydir/ # 添加demo文件到工作目录下的/mydir/ $WORKDIR/mydir/
ADD demo /mydir/ # 添加demo文件到根目录下的/mydir/
<!--
COPY指令能保留文件的元数据,如权限,访问时间等
ADD在对压缩文件操作的情况下会对其解压然后将内容复制到指定路径中,COPY则只会进行复制操作。ADD还可以通过url下载文件并复制到指定路径中
-->
- 安装软件包:使用包管理工具安装所需的软件包。
RUN apt update # 用于更新APT包管理器的软件包列表,确保正在安装的软件包是最新的
RUN apt install python3 python3-pip -y
RUN pip3 install flask
- 暴露端口:指定容器运行时需要暴露的端口。
EXPOSE 8000
<!--
一般不使用该方式,而是在构建镜像时通过-p 80:8000方式来进行端口映射
-->
- 运行命令:指定容器启动后要执行的命令。
前台进程
创建前台进程,Docker容器的前台进程是指容器启动后,在容器内部运行的第一个进程,负责维持容器的运行状态,前台进程退出,容器也将停止;没有前台进程的镜像启动容器,容器启动后立刻会自动销毁,
类似于pycharm中该状态
启动方式:
CMD ["python3", "app.py"]
或者
ENTRYPOINT["python3", "app.py"]
两者作用相同,在容器启动后都可以成为容器的前台进程
区别在于CMD执行的命令会被docker run后携带的命令覆盖
CMD["python3", "app.py"]
docker run -p 80:8000 xiaohuo:0.1 python3 app02.pypython3 app02.py # 实际执行的命令
而ENTRYPOINT则是设置容器初始化命令,docker run后携带的命令会作为参数传递给ENTRYPOINT
ENTRYPOINT["python3", "app.py"]
docker run -p 80:8000 xiaohuo:0.1 python3 app02.py
python3 app.py python3 app02.py # 实际执行的命令
也可以CMD和ENTRYPOINT可以结合使用。CMD通常用于提供默认参数,而ENTRYPOINT用于指定容器启动时要运行的命令或程序ENTRYPOINT ["python3"]
CMD ["app.py"]docker run -p 80:8000 xiaohuo:0.1 python3 app02.py
python3 app.py python3 app02.py # 实际执行的命令
数据卷
将容器内目录映射到宿主机本地,在宿主机本地修改映射文件可以实现同步修改映射的容器文件。
与容器内部的文件系统不同,本地卷的数据可以在容器被删除后仍然保留在主机上,因此可以用于持久化存储应用程序的数据。
创建数据卷
在容器创建时挂载数据卷
docker run -d -p 80:8000 -v h1:/usr/share/bin/html xiaohuo:0.1
<!--"-v" volume 表示要挂载数据卷
"html:/usr/share/bin/html" h1为数据卷名,后面的路径是容器内要映射的文件映射文件则存放在宿主机/var/lib/docker/volume/h1/_data中
-->
之后只需要对_data内的映射文件进行修改就能同步修改容器内的文件
数据卷基本操作
# 创建数据卷
docker volume create
# 查看所有数据卷dovker volume ls
# 删除指定数据卷,正在挂载的数据卷无法被删除docker volume rm
# 查看数据卷详情docker volume inspect
# 清除所有未挂载到容器数据卷,不会清除正在使用的数据卷,慎用# 在Docker中,当你删除一个镜像或容器时,它们占用的存储空间并不会立即被释放,而是被标记为可回收的存储空间RECLAIMABL,可以通过docker system df -v查看
docker volume prune
挂载数据卷到指定目录
docker run -d -p 80:8000 -v /root/mysql/:/usr/share/bin/html xiaohuo:0.1
<!--
在宿主机/root/mysql/目录下挂载容器的数据卷
-->
在Docker中,当你删除一个镜像或容器时,它们占用的存储空间并不会立即被释放,而是被标记为可回收的存储空间RECLAIMABL,可以通过docker system df -v查看
容器网络互联
容器创建时如果没有指定网络则默认使用桥接网络模式分配到"brige"网络,然而这种共享网络的方式有一定安全隐患。
通过创建自定义网络,可以将指定容器隔离在一个独立的网络中,从而限制不相关容器之间的直接通信,防止容器之间的非授权访问
容器网络基本操作
# 创建自定义网络
docker network create
# 查看所有网络docker network ls
# 删除指定网络,该网络不能有连接容器docker network rm
# 清楚没有容器连接的网络docker network prune
# 连接某容器至某网络docker network connect
# 断开某容器至某网络的连接docker network disconnect
# 显示网络的详细信息docker network inspect
在容器创建时加入网络
docker network create nw01
docker run -d -p 80:8000 --name ubuntu01 --network nw01 xiaohuo:0.1
docker run -d -p 8080:8080 --name java02 --network nw01 xiaohuo:0.1
自定义网络中容器的通信
自定义网络中的容器通信可以通过容器名来进行,也可以通过ip地址进行访问,但是ip地址可能会在容器重启一次后改变
# 进入容器内部
docker exec -it ubuntu01 bash
# 通过容器名像同网络下另一容器发送通信ping java01
其他
清除docker构建镜像的缓存
可以通过 docker system df 查看docker的磁盘使用情况
通过 docker builder prune 清除缓存