Skip to content

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"
instructdescriptione.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、CMDSHELL /bin/sh
RUN构建时执行命令,可多个 RUN 指令RUN <command>
CMDRUN、START、RESTART 触发,追加命令被替换。CMD <command>
ENTRYPOINTRUN、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