Docker
Docker 容器使用沙箱机制,相互之间不会有任何接口。
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker 可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方式来快速交付、测试、部署,可以大大减少编写代码和在生产环境中运行代码间的延迟。
- Docker 17.03 版本之后分为 CE (Community Edition) 和 EE (Enterprise Edition)
architecture
image 镜像就相当于是一个 root 系统文件。镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发软件,他包含运行某个软件所需的所有内容,包括代码、运行是、库、环境变量和配置文件。
- UnionFS 联合文件系统,Union 文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录加载到同一个虚拟文件系统(unite several directories into a single virtual filesystem)。 Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
- BootFS (boot file system) 主要包含 bootloader 和 kernal, bootloader 主要是引导加载 kernal 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是 boootfs, 这一层与我们经典的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。 当 boot 加载完成之后整合内核就都在内存之中了,此时内存的使用权已由 bootfs 转交内核,此时系统会卸载 bootfs
- RootFS RootFS (root file system ) 在 bootfs 之上,包含的就是经典 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件,rootfs 就是各种不同的操作系统发行版。
container 镜像与容器之间的关系相当与类与实例之间的关系。镜像是静态的定义,容器是镜像运行后的实体。容器可以被创建、启动、停止、删除、暂停。
Repository: 仓库可以看作是一个代码控制中心,用来保存镜像。
<namespace/image>:<tag>
安装
Debian
sh
$ apt install apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
$ chmod a+r /etc/apt/keyrings/docker.asc
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ apt update
$ apt list --all-versions docker-ce
$ apt install docker-ce=5:28.0.0-1~debian.12~bookworm
镜像配置
bash
# /var/lib/docker
# /etc/docker/daemon.json
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
EOF
$ systemctl daemon-reload
$ systemctl restart docker
commad
镜像
sh
# query
$ docker search <image>
# registry pull to local
$ docker pull <image>[:tag]
# list image
$ docker images
# remove image
$ docker rmi <id:name>
# export image
$ docker save -o <path> <image>[:tag]
# import image
$ docker load -i <path>
$ docker history
$ docker inspect <image>[:tag]
容器
sh
# image to container
$ docker run <image>[:tag]
# show cotnainer
$ docker ps
# remove container
$ docker rm <id|name>
# management container
$ docker start <id|name>
$ docker restart <id|name>
$ docker stop <id|name>
$ docker kill <id|name>
$ docker pause <id|name>
$ docker logs --tail <n> -f <id|name>
$ docker run -d centos bash -c "while ture; do echo []; sleep 1; done"
# info
$ docker inspect <id|name>
# interactive pseudo-tty active container
$ docker exec -it <id|name> bash
# copy files/folders between a container an the local filesystem.
$ docker cp <source...> <target>
volume
数据持久化,挂载关联容器文件,文件不会随容器生命周期变化被删除。 载点为绝对路径时会指定在文件系统下,若未指定载点在 /var/lib/docker/volume
下生成挂载文件,此时分为具名挂载和匿名挂载。
sh
# 具名挂载
$ docker run -v <mount-point>:<source-point> <image>:<tag>
# 权限
$ docker run -v <mount-point>:<source-point>:rw <image>:<tag>
$ docker run -v <mount-point>:<source-point>:ro <image>:<tag>
# 匿名挂载
$ docker run <image>:<tag>
# 父子容器数据共享
$ docker run -v <mount-point>:<source-point> <image>:<tag>
$ docker run --volumes-from <parent-cotnainer> <image>:<tag>
build
类似 nginx 这样作为启动后作为后台进程的容器会执行完后会停止。容器运行必须有一个前台进程如果没有,容器认为空闲从而停止容器。
下列可作镜像启动指令使容器不被停止
tail -f /dev/null
- sh -c "while true; do echo hello world; sleep 1; done"
instruct | description | e.g. |
---|---|---|
FROM | 指定基础镜像 | FROM <image>[:<tag>] |
LABEL | 添加镜像元数据 | LABEL <key1>=<value1> <key2>=<value2>... |
ARG | 传递给构建器的变量,仅构建时生效。 | ARG <key1>=<value1> <key2>=<value2>... |
ENV | 传递给容器的变量,容器内生效。 | ENV <key1>=<value1> <key2>=<value2>... |
ADD | 将文件(-,tar.gz,tar.bz,tar.xz)、url 复制到镜像 | ADD <源路径1>... <目标路径> |
COPY | 复制文件到镜像 | COPY [--chown=<user>:<group>] <源路径1>... <目标路径> |
EXPOSE | 仅仅声明端口 | EXPOSE [80,8080] |
VOLUME | 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。 | VOLUME /www |
WORKDIR | 工作目录 | WORKDIR /www |
USER | 指定后续指令的用户上下文 | USER <user>[:<group>] |
ONBUILD | 当该镜像作为另一个构建基础时,添加触发器 | |
STOPSIGNAL | 设置发送给容器退出的调用信号 | |
HEALTHCHECK | 周期性检查容器健康的命令 | |
SHELL | 默认 shell 用于 RUN、ENTRYPOINT、CMD | SHELL /bin/sh |
RUN | 构建时执行命令,可多个 RUN 指令 | RUN <command> |
CMD | RUN、START、RESTART 触发,追加命令被替换。 | CMD <command> |
ENTRYPOINT | RUN、START、RESTART 触发,可追加命令。 | ENTRYPOINT <command> |
Dockerfile
FROM centos:centos7
ENV BASEDIR /usr/local
WORKDIR $BASEDIR
ADD jdk-8u211-linux-x64.tar.gz $BASEDIR
ADD apache-tomcat-9.0.68.tar.gz $BASEDIR
ENV JAVA_HOME=$BASEDIR/jdk1.8.0_211
ENV JRE_HOME=$JAVA_HOME/jre
ENV CATALINA_HOME=$BASEDIR/apache-tomcat-9.0.68
ENV CATALINA_BASE=$BASEDIR/apache-tomcat-9.0.68
ENV CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/bin/bootstrap.jar:$CATALINA_HOME/bin/tomcat-juli.jar
ENV PATH=$PATH:$JAVA_HOME/bin;$JRE_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/lib
EXPOSE 8080
# CMD ["catalina.sh", "run"]
CMD startup.sh && tail -F /usr/local/apache-tomcat-9.0.68/logs/catalina.out
sh
$ docker build -t <image>[:<tag>] .
$ docker run -d -p [port]:8080 --name [name] -v [path]:/usr/local/apache-tomcat-9.0.22/webapps -v [path]:/usr/local/apache-tomcat-9.0.22/logs [image]:[tag]
login
bash
$ docker login -u [] -p []
# 发布到 hub.docker.com
$ docker push [image]:[tag]
# create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
$ docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
network
bash
# 创建静态docker网络
$ sudo docker network create --subnet 172.18.0.1 local-net
# 创建容器联接到docker网络并指定ip
$ sudo docker run -d --name redis --network local-net
--ip 172.18.0.2 redis:7.0-alpine
# 容器加入docker网络并指定ip
$ sudo docker network connect local-net --ip 172.18.0.2
redis
# 断开网络
$ sudo docker network disconnect local-net $(docker ps -qf name=redis)
# veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着
# docker0 相当与路由器,所有请求发送到 x.x.x.1 转发到容器。
# 172.17.0.3 ping 172.17.0.2
$ docker exec -it 3449fc6fe9aa ping 172.17.0.2
# 255.255.0.1/16
# 二进制ipv4 地址
# 32-16=16 指示只i使用前16为二进制
# 那么可用地址数 = 2^8 - 2
# 2 = 255.255.255.255 和 0.0.0.0
0000 0000.0000 0000.0000 0000.0000 0000
实名联接
bash
# --link # 就是在 /etc/hosts 下添加绑定链接的配置
# 目前以不推荐使用 --link 进行配置
$ docker run --link [container id] [image][:tag]
自定义网络
bash
# 解决了 docker0 --link 繁琐问题
# 网络模式:--net birdge (默认)
# birdge 桥接
# none 不配置网络(默认)
# host 和宿主机共享网络
# container 容器网络连通
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 [name]
$ docker network inspect [name]
$ docker network connect [name] [container id]
$ docker network create --drvier bridge --subnet 192.168.0.0/24 --gateway
# docker run -d --network <network-name> --ip <ip> <image>
# docker network connect --ip <ip> <network-name> <container-name>
docker-compose
install
sh
$ cd /usr/local/bin
# curl -L|--location 自动跟随重定向,当服务器返回3xx重定向状态码(如301、302)会自动请求新的 URL 地址,知道获取内容。
$ curl -L "https://github.com/docker/compose/releases/download/v2.36.0/docker-compose-$(uname -s)-$(uname -m)" -o ./docker-compose
$ chmod +x docker-compose
$ ln -s $(pwd)/dokcer-compose /usr/bin/dokcer-compose
$ docker-compose -v
# Docker Compose version v2.36.0
通过yaml
脚本启动镜像
bash
# docker 1.13.1 搭配 docker-compose 2.2.2 可行
$ curl -L https://get.daocloud.io/docker/compose/releases/download/v2.2.2/docker-compose-`uname -s`-`uname -m` /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 安装检查
$ docker-compose version
# 后台执行服务
$ docker-compose up -d
portainer
docker 的图像化管理工具
bash
$ docker run -d --name portainer-ce --restart=always -p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/var/lib/protainer/data:/data \
portainer/portainer-ce