![]() |
越狱的排球 · 【坚果M7投影仪如手机般大小 ...· 4 月前 · |
![]() |
俊秀的滑板 · 中南大学 liuhui· 7 月前 · |
![]() |
从容的柿子 · 2023年河南省开封市事业单位第一批教师招聘 ...· 8 月前 · |
![]() |
活泼的红金鱼 · Install Oracle ...· 10 月前 · |
![]() |
豪爽的毛豆 · Coding Games and ...· 10 月前 · |
Docker 学习笔记
Docker 是一个跨平台、可移植并且简单易用的容器解决方案。基于 Go 语言开发。
Docker 可在容器内部快速自动化地部署应用,并通过操作系统内核技术(namespaces、cgroup等)为容器提供资源隔离和安全保障。
《Docker — 从入门到实践》 – docker 中文白皮书
https://yeasy.gitbooks.io/docker_practice/content/
https://github.com/yeasy/docker_practice
learn to build and deploy your distributed applications easily to the cloud with docker
https://docker-curriculum.com/
最终程序员们从传统运输业找到了答案。
几十年前,运输业面临着类似的问题。
每一次运输,货主与承运方都会担心因货物类型的不同而导致损失,比如几个铁桶错误地压在了一堆香蕉上。另一方面,运输过程中需要使用不同的交通工具也让整个过程痛苦不堪:货物先装上车运到码头,卸货,然后装上船,到岸后又卸下船,再装上火车,到达目的地,最后卸货。一半以上的时间花费在装、卸货上,而且搬上搬下还容易损坏货物。 这也是一个N x M 的矩阵。
集装箱的发明解决这个难题。
任何货物,无论钢琴还是保时捷,都被放到各自的集装箱中。集装箱在整个运输过程中都是密封的,只有到达最终目的地才被打开。标准集装箱可以被高效地装卸、重叠和长途运输。现代化的起重机可以自动在卡车、轮船和火车之间移动集装箱。集装箱被誉为运输业与世界贸易最重要的发明。
Docker 将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。
Docker 可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 仓库名:标签 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
以 Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest
镜像是容器的基础,每次执行 docker run 的时候都会指定哪个镜像作为容器运行的基础。
docker镜像的文件内容以及一些运行docker 容器的配置文件组成了docker 容器的静态文件系统运行环境 ——— rootfs。
rootfs 是docker 容器在启动时内部进程可见的文件系统,即 docker 容器的根目录。rootfs 通常包含一个操作系统运行时所需的文件系统。
在传统的linux 操作系统内核启动时,首先挂载一个只读的rootfs,当系统检测其完整性以后,再将其切换为读写模式。在docker daemon 为docker 容器挂载rootfs 时,沿用了上述方法,即将rootfs 设为只读模式,挂载完毕后,利用联合挂载(union mount)技术在已有的只读rootfs 上在挂载一个读写层。
镜像的特点:
分层:docker 镜像是采用分层方式构建的,每个镜像都由一系列的“镜像层”组成
写时复制:每个容器启动时不需要单独复制一份镜像文件,而是将所有镜像层以只读的方式挂载到一个挂载点,在其上覆盖一个可读写的容器层。
内容寻址:对镜像内容计算校验和,生成内容哈希,减少冲突。
联合挂载:联合挂载技术可以在一个挂载点同时挂载多个文件系统,将挂载点的原目录与被挂载的内容进行整合,使得最终可见的文件系统将会包含整合之后的各层的文件和目录。
$ docker save -o hello-world.tar hello-world:latest $ tar -xvf hello-world.tar -C hello-world-image cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/ cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/VERSION cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/json cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/layer.tar fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e.json manifest.json repositories
1、manifest.json 清单(manifest)文件是一段元数据,描述了该镜像中的内容。
"Config":"fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e.json", "RepoTags":[ "hello-world:latest" "Layers":[ "cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/layer.tar"2、image-id.json文件
还有个前几位和 image-id 相同的 image-idxxx.json 文件,详细描述了镜像的信息。3、此外有好多子目录,每个子目录是文件系统的一层(layer),每个子目录里也有一个 json 描述当前层的元数据信息。
container 容器
image和container的区别?
docker文件系统
UnionFS联合文件系统
联合文件系统(Union File System):2004年由纽约州立大学石溪分校开发,它可以把多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的。UnionFS允许只读和可读写目录并存,就是说可同时删除和增加内容。UnionFS应用的地方很多,比如在多个磁盘分区上合并不同文件系统的主目录,或把几张CD光盘合并成一个统一的光盘目录(归档)。另外,具有写时复制(copy-on-write)功能UnionFS可以把只读和可读写文件系统合并在一起,虚拟上允许只读文件系统的修改可以保存到可写文件系统当中。
Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
使用mount创建一个AUFS文件系统
Linux AUFS 文件系统
https://www.cnblogs.com/sparkdev/p/11237347.htmlAUFS
AUFS(AnotherUnionFS)就是一种 Union FS。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。
OverlayFS
OverlayFS 是和 AUFS 相似的联合文件系统(union filesystem),它有如下特点:
设计简洁;
内核 3.18 开始已经并入内核主线
可能更快OverlayFS 将单个 Linux 主机上的两个目录进行分层,然后将它们表示为一个目录。这些目录就叫做 layers,这个过程就被叫做 union mount。OverlayFS 将靠下一层的目录叫做 lowerdir,将靠上一层的叫做 upperdir。然后经过处理后我们看到的那个目录叫做 merged。
docker支持的UFS
$ docker info |grep "Storage" Storage Driver: overlay2
初代 docker 默认的存储驱动是 AUFS,后来 docker 默认的存储驱动已经演进到了 overlay2
每个容器都有它们自己的文件系统视图,Docker 获取镜像所有的层,并使它们层叠在一起,以呈现为文件系统的一个视图。这个技术称为 Union Mounting,Docker 支持 Linux 上的几个 Union Mount 文件系统,主要是 OverlayFS 和 AUFS。
Docker的文件系统是如何工作的?
Docker镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(译者注:镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。
为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。
一个容器中修改了基础镜像是否会影响其他容器?
Docker容器文件系统volume 卷
容器中的文件存在形式复杂,宿主机访问容器的文件很困难。 多个容器之间的数据无法共享。 容器一旦被删除,容器产生的数据将丢失。 数据卷就是为了解决以上问题出现的。volume 是存在于一个或多个容器中的特定文件或文件夹,这个目录以独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久化提供便利。 volume 在容器创建时就会初始化,所以运行时就可以使用。
在不同容器间共享和重用。
对volume 中数据的操作会马上生效。
对volume 中的数据操作不会影响到镜像本身。
volume 的生存周期独立于容器的生存周期,即使删除容器,volume依然存在,没有任何容器使用它,也不会被docker 删除。按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。
数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用
docker rm -v
这个命令。docker Daemon与client
docker daemon 接受 docker api 的请求,并管理docker 中定义的对象:镜像、容器、网络、数据卷等。
docker client 是大多数人与docker 打交道的工具,比如当你输入docker run命令时,docker client 将命令发到 daemon执行。docker 网络
Network Overview
https://docs.docker.com/network/安装 Docker 时,它会自动创建 3 个网络。可以使用
docker network ls
命令列出这些网络。
这 3 个网络包含在 Docker 实现中。运行一个容器时,可以使用--net
标志指定您希望在哪个网络上运行该容器。您仍然可以使用这 3 个网络。bridge 网络表示所有 Docker 安装中都存在的 docker0 网络。除非使用
docker run --net=<NETWORK>
选项另行指定,否则 Docker 守护进程默认情况下会将容器连接到此网络。在主机上使用 ifconfig命令,可以看到此网桥是主机的网络堆栈的一部分。
none 网络在一个特定于容器的网络堆栈上添加了一个容器。该容器缺少网络接口。
host 网络在主机网络堆栈上添加一个容器。您可以发现,容器中的网络配置与主机相同。
bridge
即桥接网络,以桥接模式连接到宿主机,即宿主机和容器之间通过 docker0 虚拟网卡连到同一个局域网。bridge是默认的网络模式host
宿主网络,即与宿主机共用网络,这种模式相当于没有网络隔离,好处是和宿主机处于同一网络,可随意访问,都不用-p
做端口映射了。none
则表示无网络,容器将无法联网
overlay
跨主机网络。
在早期的docker版本中,是不支持跨主机通信网络驱动的,也就是说明如果容器部署在不同的节点上面,只能通过暴露端口到宿主机上,再通过宿主机之间进行通信。
docker 1.9 之后,随着docker swarm集群的推广,docker也有了自家的跨主机通信网络驱动,名叫overlay,overlay网络模型是swarm集群容器间通信的载体,将服务加入到同一个网段上的Overlay网络上,服务与服务之间就能够通信。bridge
Use bridge networks
https://docs.docker.com/network/bridge/安装 Docker 的时候,会在宿主机安装一个虚拟网卡 docker0, 它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
$ ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:88ff:fe56:8251 prefixlen 64 scopeid 0x20<link> ether 02:42:88:56:82:51 txqueuelen 0 (Ethernet) RX packets 915966 bytes 2933746454 (2.7 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 875092 bytes 62233810 (59.3 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。例如Linux下一般是 172.17.0.1 , 并不固定。
它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。
这些值都可以在服务启动的时候进行配置。host
Use host networking
https://docs.docker.com/network/host/host 网络和主机之间没有隔离,和主机共享一个 network namespace.
注意:使用 host 网络模式时,端口映射不起作用。 docker run 时的
-p, --publish
,-P, --publish-all
参数会被忽略,并产生一条警告:
WARNING: Published ports are discarded when using host network modeMac和Windows上没有host网络
Mac中主机和容器网络互通解决方案
2、宿主机访问容器
通过 -p 端口映射。
例如docker run -p 8081:80 -d nginx
之后在主机上通过 localhost:8081 可直接访问容器内的 80 端口Networking features in Docker Desktop for Mac
https://docs.docker.com/docker-for-mac/networking/docker-proxy
https://learn.lianglianglee.com/专栏/由浅入深吃透%20Docker-完/11%20%20组件组成:剖析%20Docker%20组件作用及其底层工作原理.md
根据 docker-proxy 端口占用找对应容器
root 75958 11931 0 Aug21 ? 00:00:00 /usr/local/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 192.168.42.2 -container-port 8080
3、docker ps |grep 8080 端口,能看到是哪个容器在使用 8080 端口
4、docker inspect container-id |grep IPAddress 能看到使用 8080 端口的容器的 ip 就是 192.168.42.2
Docker 原理
chroot 隔离文件系统
namespace 隔离进程访问
cgroups 隔离资源使用docker 并不是彻底的虚拟化,不同容器之间会共享内核。
Linux 虚拟机是完全的虚拟化,内核隔离。chroot
Linux Namespace
DOCKER基础技术:LINUX NAMESPACE(上)
https://coolshell.cn/articles/17010.htmlLinux CGroup
容器 request/limit 利用 cgroup cpu 公平调度器实现。
DOCKER基础技术:LINUX CGROUP
https://coolshell.cn/articles/17049.htmlRunC
RunC 简介
https://www.cnblogs.com/sparkdev/p/9032209.htmlRunC 是一个轻量级的容器运行工具,用来运行按照 OCI(Open Container Initiative) 标准格式打包的容器。
RunC 是用 golang 创建的项目。
RunC 是标准化容器运行时的一个实现,是 docker 内置的默认容器运行时。containerd
Containerd 简介
https://www.cnblogs.com/sparkdev/p/9063042.htmlcontainerd 是一个工业级标准的容器运行时,可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。
containerd 是从 docker 中分离出来的,或者说 containerd 本身是 docker 的一部分。containerd 并不是直接面向最终用户的,而是主要用于集成到更上层的系统里,比如Swarm, Kubernetes, Mesos等容器编排系统。
containerd 以 Daemon 的形式运行在系统上,通过 unix domain socket 暴露很底层的 gRPC API,上层系统可以通过这些 API 管理机器上的容器。每个 containerd 只负责一台机器,Pull 镜像,对容器的操作(启动、停止等),网络,存储都是由 containerd 完成。具体运行容器由 runC 负责,实际上只要是符合 OCI 规范的容器都可以支持。安装Docker
Docker 从 1.13 版本之后采用时间线的方式作为版本号,分为社区版 CE 和企业版 EE。
社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经过官方测试认证过的基础设施、容器、插件等。
Docker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。
Docker CE 分为 stable test 和 nightly 三个更新频道。每六个月发布一个 stable 版本 (18.09, 19.03, 19.09…)。CentOS 安装 Docker CE
Get Docker Engine - Community for CentOS
https://docs.docker.com/install/linux/docker-ce/centos/CentOS 安装 Docker CE
https://yeasy.gitbooks.io/docker_practice/install/centos.htmlDocker 入门教程
http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html前提条件:
1 安装 Docker Engine - Community 需要 CentOS 7 版本及以上,老版本不支持。
2 需要开启 centos-extras yum repo,默认是开启的。安装 docker repo
1 安装 yum 仓库管理工具 yum-utils, 以及 device-mapper-persistent-data, lvm2
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \
2 安装 docker repo
$ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
安装完可以在
/etc/yum.repos.d/
中看到docker-ce.repo
文件docker-ce.repo
中默认只有docker-ce-stable
是开启的,即只开启稳定版的repo
yum 安装最新版 Docker
containerd.io.x86_64 0:1.2.10-3.2.el7 docker-ce.x86_64 3:19.03.5-3.el7 docker-ce-cli.x86_64 1:19.03.5-3.el7 作为依赖被安装: container-selinux.noarch 2:2.107-3.el7
sudo yum install docker-ce docker-ce-cli containerd.io
我安装的版本信息启动 Docker 并验证
$ sudo docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
将当前用户加入docker用户组
重启 Docker
sudo systemctl restart docker
容器会全部停止,之后需要重启容器Docker升级到指定版本
停止 docker 服务
systemctl stop docker
查看当前版本
rpm -qa | grep docker
# rpm -qa | grep docker nvidia-container-runtime-2.0.0-1.docker17.06.2.x86_64 docker-ce-17.06.2.ce-1.el7.centos.x86_64 nvidia-docker2-2.0.3-1.docker17.06.2.ce.noarch
删除当前版本
yum remove docker-ce-17.06.2.ce-1.el7.centos.x86_64
Mac 安装 Docker CE
Install Docker Desktop on Mac
https://docs.docker.com/docker-for-mac/install/macOS 安装 Docker Desktop CE
https://yeasy.gitbooks.io/docker_practice/install/mac.htmlDocker Desktop for Mac 要求系统最低为 2010 年以后的 Mac 机型,准确说是带 Intel MMU 虚拟化的, macOS 10.13 及以上版本, 最低 4GB 内存。
如果不满足已上要求,可以使用 Docker Toolbox 安装 Docker 来代替 Docker Desktop, Docker Toolbox 使用 Oracle VirtualBox 虚拟机而不是 HyperKit 虚拟机。Homebrew 安装 Docker Desktop for Mac
查看 docker 版本
docker --version
$ docker --version Docker version 19.03.5, build 633a0ea
启动一个 nginx 验证
docker run -d -p 80:80 --name nginx --rm nginx
docker run -d -p 80:80 --name nginx --rm nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx 000eee12ec04: Pull complete eb22865337de: Pull complete bee5d581ef8b: Pull complete Digest: sha256:50cf965a6e08ec5784009d0fccb380fc479826b6e0e65684d9879170a9df8566 Status: Downloaded newer image for nginx:latest 76986f1e2fffac5174f5cfa23a0988f891762bfc73904aad142d1c96c9dff75e
会自动从 docker hub 上下载最新版 nginx 镜像并启动
服务运行后,可以访问 http://localhost,如果看到了 “Welcome to nginx!”,就说明 Docker Desktop for Mac 安装成功了。Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
Dockerfile reference
https://docs.docker.com/engine/reference/builder/Docker 最佳实践
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
FROM 指定基础镜像
VOLUME 创建挂载点
VOLUME 在镜像中创建挂载点
VOLUME 后的目录格式可以是纯文本的目录,空格分割的多个目录,或者json格式的字符串数组VOLUME /var/log VOLUME /var/log /var/db VOLUME ["/data1","/data2"]
相比于 docker run 时 -v 指定目录映射, VOLUME 指令可实现通过此镜像创建的容器内都有一个预先创建好的目录,当然使用 docker run -v 也完全可以代替 VOLUME 指令。
COPY 复制文件
ADD 更高级的复制文件(自动解压)
相比 COPY, ADD 其实就增加了2个特性:
1、ADD 指令可以让你使用 URL 作为 src 参数。当遇到 URL 时候,可以通过 URL 下载文件并且复制到 dest
2、ADD 的另外一个特性是有能力自动解压文件。如果 src 参数是一个可识别的压缩格式(tar, gzip, bzip2, etc)的本地文件(所以实现不了同时下载并解压),就会被解压到指定容器文件系统的路径 destWORKDIR 指定工作目录
WORKDIR <工作目录路径>
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录EXPOSE 声明端口
RUN 执行命令
RUN apk add --no-cache tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/shanghai" > /etc/timezone \ && rm -rf /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cache ## 清除缓存 RUN chmod +x /root/apps/start_jar.sh
第一个安装时区的多条命令放在一个 RUN 中,保证构建在同一层镜像
CMD 容器启动命令
例如
CMD echo "Hello world"
运行容器docker run -it [image]
将输出 Hello world,但当后面加上一个命令,比如docker run -it [image] /bin/bash
,CMD 会被忽略掉,命令 bash 将被执行,会进入容器。ENTRYPOINT 入口点
RUN/CMD/ENTRYPOINT 区别
ENTRYPOINT ["/usr/bin/rethinkdb"] CMD ["--help"]
这个 dockerfile 里 ENTRYPOINT 后面还有个 CMD 的考虑是,如果 docker run 没有参数,CMD(–help)将成为 ENTRYPOINT 的默认参数,输出帮助信息,例如 docker run rethinkdb 时就会输出帮助信息。
当 docker run 有参数时会代替 CMD 命令,例如 docker run -it rethinkdb bash 可以进入容器。
Shell 格式与 Exec 格式
RUN/CMD/ENTRYPOINT 命令的格式有两种:
1、shell 格式RUN/CMD/ENTRYPOINT <命令>
就像直接在命令行中输入的命令一样。
例如RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html RUN yum install -y vim CMD echo "hello zhurs" ENTRYPOINT echo "hello zhurs"
2、exec 格式
RUN/CMD/ENTRYPOINT ["可执行文件", "参数1", "参数2"]
这更像是函数调用中的格式
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以
例如
RUN ["yum", "install", "-y", "vim"] CMD ["bin/echo", "zhurs"] ENTRYPOINT ["/bin/echo", "hello, $wd"] ENTRYPOINT ["java", "-jar", "/blog-server.jar"]
USER 指定容器用户
USER <user>[:<group>]
或USER <UID>[:<GID>]
指定运行容器时的用户名或 UID,后续的 RUN 等指令也会使用指定的用户身份
使用 USER 指定用户时,可以使用用户名、UID 或 GID,或是两者的组合
使用 USER 指定用户后,Dockerfile 中后续的命令 RUN、CMD、ENTRYPOINT 都将使用该用户也可以使用 docker run -u 指定用户
镜像压缩技巧
FROM iregistry.baidu-int.com/baidu-base/golang:1.19-alpine3.16 AS builder COPY --from=builder /app/bin/ /app/bin/
二、docker export/import 镜像导出再导入可压缩镜像
Docker API
https://docs.docker.com/engine/api/sdk/examples/
containers/json 查看容器列表
curl --unix-socket /var/run/docker.sock http://localhost/v1.43/containers/json "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772", "Names":["/tender_wing"], "Image":"bfirsh/reticulate-splines",
Docker 常用命令
Command-line reference
https://docs.docker.com/engine/reference/commandline/cli/docker info 查看docker信息
# docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 18.06.1-ce Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: false Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local Network: bridge host macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog Swarm: inactive Runtimes: nvidia runc Default Runtime: runc Init Binary: docker-init containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e runc version: 69663f0bd4b60df09991c08812a60108003fa340 init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 3.10.0-514.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 24 Total Memory: 251.6GiB Name: myapp ID: UF76:IPSA:VE7G:YD67:PQRT:WU4E:3EKX:2J7F:36PQ:BSOT:N2CV:XMFX Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false
查看 Root Dir
$ docker info |grep "Docker Root Dir" Docker Root Dir: /var/lib/docker
查看 docker 的 cgroup driver
$ docker info |grep Cgroup Cgroup Driver: cgroupfs
docker system df 查看docker磁盘占用
https://docs.docker.com/engine/reference/commandline/system_df/
docker system df
查看 docker 磁盘占用汇总信息docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 433 42 117.4GB 97.11GB (82%) Containers 103 89 2.145GB 1.464GB (68%) Local Volumes 9 6 116B 58B (50%) Build Cache 0 0 0B 0B
RECLAIMABLE 是空闲镜像(没有任何容器使用的镜像)的大小,空闲镜像可以用命令
docker image prune -a
清理查看docker容器占用磁盘空间大小
docker system df 加 -v 参数显示详细的磁盘占用信息,能看到每个镜像、容器、卷的磁盘占用情况:
$ docker system df -v Images space usage: REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS blog latest 3fc20337e23a 3 hours ago 975MB 0B 975MB 1 elasticsearch 8.6.1-ik b1e6c57fe659 5 months ago 1.297GB 0B 1.297GB 1 gogs/gogs latest ead46421307d 3 years ago 92.38MB 0B 92.38MB 1 nginx alpine 377c0837328f 3 years ago 19.72MB 0B 19.72MB 1 Containers space usage: CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES a7faa3438b30 blog "java -jar /blog-ser…" 1 0B 3 hours ago Up 3 hours blog 3bd1f9b14c43 nginx:alpine "nginx -g 'daemon of…" 0 2B 7 weeks ago Up 7 weeks nginx 7ee16ad38348 elasticsearch:8.6.1-ik "/bin/tini -- /usr/l…" 0 98.8MB 5 months ago Up 5 months es f33daa8d3e09 gogs/gogs "/app/gogs/docker/st…" 1 5.57kB 5 months ago Up 5 months gogs Local Volumes space usage: VOLUME NAME LINKS SIZE 947b26afba6c51e5d72f83f523a93fe3be7b7b83f32edc62175a8e858585ee12 0 32.77kB 9f10a334ac3293f0e1ebcb880e1947c55017d0d878ba8d40b3925b98e494c9a1 0 32.77kB 58f94b049406ebb796379a43061c9e81f33a309d295beb1e27c50f14a5fec417 1 0B 716a30cd87333e7ee12d0e91cb55ad4a4005db78348c0696cfbd7568246ffab6 1 33.6kB 08d2a5847d3b9e96b595e6efa29fdbe66cb6148eb285066069e17397463e0950 0 32.77kB 317fdf41419fa5ac3ad7330a2c105452065e5d0846920e4ca32e9952790301dd 0 32.77kB 8817b7c05b024d5c03d78f8ce8e5c133ca79d5e79570583135b9d892f7442785 0 0B Build cache usage: 0B CACHE ID CACHE TYPE SIZE CREATED LAST USED USAGE SHARED
docker/containers 目录磁盘占用大清理
1、找到 docker 根目录
docker info |grep “Docker Root Dir”
默认是 /var/lib/docker2、进入 containers 子目录,里面每个容器对应一个目录,目录名是容器ID,docker ps 结果的第一列就是容器ID的前缀
每个容器目录中有 容器ID-json.log 的日志文件,通常会比较大,可以直接>contain-id-json.log
清理掉限制 docker 控制台日志大小
新建或修改 docker 配置 /etc/docker/daemon.json
"max-concurrent-downloads": 10, "log-driver": "json-file", "log-level": "warn", "log-opts": { "max-size": "50m", "max-file": "5" "data-root": "/data/lib/docker"单个日志文件最大 50m,最多 5 个日志文件,日志自动滚动:
34M e5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log 48M e5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.1 48M e5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.2 48M e5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.3 48M e5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.4
重启docker:
systemctl daemon-reload systemctl restart docker
docker system prune 系统清理
https://docs.docker.com/engine/reference/commandline/system_prune/
docker system prune 会清理
已停止的容器 没被使用的网络 docker build 缓存 docker image prune -a 清理悬空镜像
https://docs.docker.com/engine/reference/commandline/image_prune/
docker image prune -a
命令可批量清理悬空镜像docker images 看到的 none 镜像是悬空镜像(dangling images),即无标签、且不被容器使用的镜像。
REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 5eaed6e23874 10 minutes ago 741MB
docker rmi 批量删除none镜像
docker search
docker search zookeeper NAME DESCRIPTION STARS OFFICIAL AUTOMATED zookeeper Apache ZooKeeper is an open-source server wh… 1075 [OK] jplock/zookeeper Builds a docker image for Zookeeper version … 165 [OK] wurstmeister/zookeeper 145 [OK]
docker network
docker network create
docker run 运行容器
docker run
https://docs.docker.com/engine/reference/commandline/run/
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
以镜像 IMAGE 启动一个容器, 如果 IMAGE 不存在,会从默认仓库 Docker Hub 上下载此镜像,如果不指定 tag 默认是 latest,启动容器后执行命令 COMMAND例1
docker run -it --rm ubuntu:18.04 bash
直接运行 ubuntu 镜像并进入启动的 Ubuntu 容器
ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash例2
docker run -it adoptopenjdk/openjdk8:centos bash
会直接自动下载 centos+jdk 镜像,run 镜像,并进入容器内参数
-d, --detach
让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下-e, --env list
启动容器时增加环境变量-p, --publish <宿主端口>:<容器端口>
映射宿主端口和容器端口,-p
标记可以多次使用来绑定多个端口。例如-p 80:8080
映射本机 80 端口到容器内的 8080 端口-P, --publish-all
随机映射宿主机上一个 49000~49900 之间的端口到容器内部的网络端口--name string
指定启动的容器的名字--restart string
容器退出后的重启策略,默认是no
,--restart=always
可保持容器一直运行--rm
容器退出后随之将其删除。默认情况下,为了启动失败时查错,退出的容器并不会立即删除,除非手动docker rm
。
-it
进入容器
--network,--net
指定容器网络模式
-v
绑定文件/文件夹挂载目录
-v A:B
时如果容器中目录 B 不存在,会先在 contanier 中创建目录 B,再将本地目录 A 中的所有文件 copy 到 B 中 如果本地目录 A 不存在,可自动创建本地目录 A 若果 A 和 B 都存在,会用本地目录 A 中的内容覆盖容器目录 B 中的内容
-v
可以出现多次,挂载多个不同的目录。容器销毁后,启动容器时创建的宿主机目录不会销毁,容器运行过程中对目录的操作也都会保留在宿主机。
Docker volume 挂载时文件或文件夹不存在
https://segmentfault.com/a/1190000015684472Use volumes
https://docs.docker.com/storage/volumes/
--mount
挂载卷
-u
指定容器的用户和组例如
docker run -u 1000:1000 -it ubuntu bash
docker run -u centos -it centos:7 bash
--privileged
特权模式–platform 指定架构
M1 Mac 上运行 amd64/x86_64 架构镜像,可以指定
--platform linux/amd64
参数docker run -d --rm \ --platform linux/amd64 \ -p 8001:8001 \ --name blog \ -v /var/log/spring:/var/log/spring \ -e "SPRING_PROFILES_ACTIVE=local" \
如果镜像本身是 amd64/x86_64 架构的,不需要指定,但 docker run 会报警告:
WARNING: The requested image’s platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
容器无法启动问题排查
1、docker ps -a 能显示启动失败的容器,然后 docker logs -f 看启动日志有无报错
2、docker inspect 看容器信息3、如果 docker ps -a 也看不到容器,可以去掉
-d
后台运行参数,前台运行,而是-it
把容器日志打印到前台,看有什么报错。docker push 推镜像
https://docs.docker.com/engine/reference/commandline/push/
推镜像到 registry
docker push image[:tag]docker image inspect 查看镜像详细信息
https://docs.docker.com/engine/reference/commandline/image_inspect/
docker image inspect 查看镜像的架构
docker image inspect adoptopenjdk/openjdk8:centos "Id": "sha256:5c4f7308100d908ec26e8264a76d76b55591b405a76b581271dbc435c30cfbf2", "RepoTags": [ "adoptopenjdk/openjdk8:centos" "RepoDigests": [ "adoptopenjdk/openjdk8@sha256:56e00eb7fb3fb82dacb647590c0657534df2eb77605b83e4e706a38151eb082f" "Parent": "", "Comment": "buildkit.dockerfile.v0", "Created": "2023-07-01T15:09:31.842619662Z", "Container": "", "ContainerConfig": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": null, "Cmd": null, "Image": "", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null "DockerVersion": "", "Author": "", "Config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "LANG=en_US.UTF-8", "LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8", "JAVA_VERSION=jdk8u372-b07", "JAVA_HOME=/opt/java/openjdk" "Cmd": [ "/bin/bash" "Image": "", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20201113", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS", "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00", "org.opencontainers.image.licenses": "GPL-2.0-only", "org.opencontainers.image.title": "CentOS Base Image", "org.opencontainers.image.vendor": "CentOS" "Architecture": "arm64", "Variant": "v8", "Os": "linux", "Size": 1268913926, "VirtualSize": 1268913926, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/f4af2886d00a730fa35c6777754ce4ee11e1481ff22bf052f65933e70643f138/diff:/var/lib/docker/overlay2/5756458d0749a7f71398bf8162286f5cafefe39d499e04b2125662243c86ee56/diff", "MergedDir": "/var/lib/docker/overlay2/4bccc3a2faf71c2af258c3c7e80743331c5d72e69dc9d27c7a631406526a959c/merged", "UpperDir": "/var/lib/docker/overlay2/4bccc3a2faf71c2af258c3c7e80743331c5d72e69dc9d27c7a631406526a959c/diff", "WorkDir": "/var/lib/docker/overlay2/4bccc3a2faf71c2af258c3c7e80743331c5d72e69dc9d27c7a631406526a959c/work" "Name": "overlay2" "RootFS": { "Type": "layers", "Layers": [ "sha256:65f23ff12f4df9625427d229db82655bdadd805108d3431520673d79198419ff", "sha256:010044c2a811335b6122c7a8d972c3e5a4f2a1f68a8253e0af581e3709179706", "sha256:0ede7ac16aa01ae57ed91a33faffd02eb95b81692791460dc234c68e60588489" "Metadata": { "LastTagTime": "0001-01-01T00:00:00Z"
docker manifest inspect 查看镜像的manifest列表
有的镜像支持多架构,比如 https://hub.docker.com/r/adoptopenjdk/openjdk8/tags?page=1&name=centos
可以通过 docker manifest inspect 查看镜像支持哪些架构当用户获取一个镜像时,Docker 引擎会首先查找该镜像是否有 manifest 列表,如果有的话 Docker 引擎会按照 Docker 运行环境(系统及架构)查找出对应镜像(例如 golang:alpine)。如果没有的话会直接获取镜像(例如上例中我们构建的 username/test)。
docker manifest inspect adoptopenjdk/openjdk8:centos "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 956, "digest": "sha256:099e5eda268dc834873028c94eb7031d2acb2dad0ce92edccee78d6fd7666b7b", "platform": { "architecture": "arm64", "os": "linux", "variant": "v8" "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 953, "digest": "sha256:c185c64ed5993198248bf8aad74e706077b34ee30f7d0260e19c55397ac0f2f2", "platform": { "architecture": "arm", "os": "linux", "variant": "v7" "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 954, "digest": "sha256:65147bda6f81bfba8922d4c3ae896184551ac5d8fe750e3ba9916846b9eadb91", "platform": { "architecture": "ppc64le", "os": "linux" "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 954, "digest": "sha256:d2c6b89782cc256d9cef8b4dd72623f7594eb935ba62ba762ddfc17aaace8bbb", "platform": { "architecture": "amd64", "os": "linux"
docker pull 下载镜像
https://docs.docker.com/engine/reference/commandline/pull/
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
具体的选项可以通过 docker pull –help 命令看到
Docker 镜像仓库地址:地址的格式一般是<域名/IP>[:端口号]
。默认地址是 Docker Hub。
仓库名:如之前所说,这里的仓库名是两段式名称,即<用户名>/<软件名>
。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。例如
docker pull ubuntu:18.04
上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub 获取镜像。
而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。–platform 指定架构
有的镜像同一 tag 提供多架构的,可通过 –platform 参数指定架构
docker pull adoptopenjdk/openjdk8:centos –platform amd64
docker pull centos:7 –platform linux/amd64修改docker镜像存储位置
注意:Mac 虽然
docker info
看到的 Docker Root Dir 也是/var/lib/docker
, 但其实镜像并不在这里,而是在$HOME/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw
这个单独的文件中,并且无法修改。解决方法:
软链接
systemctl stop docker # 关闭 docker 服务 mv /var/lib/docker /var/lib/docker.bak # 备份当前 docker 镜像文件目录 ln -s /data/docker /var/lib/docker # 设置软连接,其中 /data/docker 目录为新的存放 docker 镜像目录 cp -rp /var/lib/docker.bak /data/docker # 将旧的 docker 文件拷贝过去
修改 docker 配置文件
指定镜像和容器存放路径的参数是
--graph=/var/lib/docker
,我们只需要修改配置文件指定启动参数即可。
1、修改 /etc/sysconfig/docker 配置文件
添加OPTIONS=--graph="/root/data/docker" --selinux-enabled -H fd://
2、如果 docker 是 1.12 或以上的版本,可以修改(或新建)
"graph": "/data/docker", "default-shm-size": "64g"/etc/docker/daemon.json
文件。修改后会立即生效,不需重启 docker 服务。
改为
修改docker.service服务配置
修改 docker 安装后自动创建的 linux 服务脚本
/etc/systemd/system/docker.service
改为ExecStart=/usr/bin/dockerd -g /data/docker/ -H fd://
然后
systemctl daemon-reload
重载 unit 配置文件
docker no space left on device
docker 镜像所在磁盘空间不足时 pull image 会报这个错误。
四个修改Docker默认存储位置的方法
https://blog.51cto.com/forangela/1949947docker images 列出本机镜像
docker image ls
列出镜像,等价于docker images
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 11 months ago 1.84kB
列表包含了 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间
docker image ls ubuntu
根据仓库名列出镜像docker image ls ubuntu:18.04
指定仓库名和标签列出镜像docker image ls -q
只列出镜像ID,经常用做其他命令的输入参数
docker image rm 删除本地镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
等价于docker rmi
docker image rm centos
用镜像名,也就是 仓库名:标签,来删除镜像docker image rm $(docker image ls -q redis)
删除所有仓库名为 redis 的镜像docker image rm $(docker image ls -q -f before=mongo:3.2)
删除所有在 mongo:3.2 之前的镜像docker build 构建镜像
docker build
https://docs.docker.com/engine/reference/commandline/build/
docker build [选项] <上下文路径/URL/->
-t, --tag
指定 image 文件的名字,后面还可以用冒号指定标签,例如 name:tag。如果不指定,默认的标签就是 latest-f, --file
指定 Dockerfile 文件名称,默认是 PATH/Dockerfile
docker build -t myapp .
在当前目录使用 Dockerfile 构建 myapp 镜像docker build -t myapp -f path-to-Dockerfile .
在当前目录使用 path-to-Dockerfile 构建 myapp 镜像–platform 构建多架构镜像
docker build -f devops/blog.Dockerfile --platform=amd64 -t blog .
M1 Mac 上打的镜像默认是arm64架构的
如果 Dockerfile 中指定了特定架构的基础镜像,例如
FROM ubuntu:amd64
,则构建的镜像继承了基础镜像的架构,因此也是 amd64 架构的构建上下文
如果在 Dockerfile 中这么写:
COPY ./package.json /app/
这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json, 而是复制 上下文(context) 目录下的 package.json。一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用
.gitignore
一样的语法写一个.dockerignore
,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile。
.dockerignore
.dockerignore
用于剔除不需要作为上下文传递给 Docker 引擎的文件docker history 查看镜像历史
https://docs.docker.com/engine/reference/commandline/history/
查看镜像历史
--no-trunc
不截断输出结果,不加这个选项的话 CREATED BY 中显示不全docker history zookeeper:3.4.14 IMAGE CREATED CREATED BY SIZE COMMENT 4b03fe5b3f64 2 months ago /bin/sh -c #(nop) CMD ["zkServer.sh" "start… 0B <missing> 2 months ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B <missing> 2 months ago /bin/sh -c #(nop) COPY file:9258d11b841666f1… 1.16kB <missing> 2 months ago /bin/sh -c #(nop) ENV PATH=/usr/local/openj… 0B <missing> 2 months ago /bin/sh -c #(nop) EXPOSE 2181 2888 3888 0B <missing> 2 months ago /bin/sh -c #(nop) VOLUME [/data /datalog /l… 0B <missing> 2 months ago /bin/sh -c #(nop) WORKDIR /zookeeper-3.4.14 0B <missing> 2 months ago |2 DISTRO_NAME=zookeeper-3.4.14 GPG_KEY=3F7A… 60MB <missing> 2 months ago /bin/sh -c #(nop) ARG DISTRO_NAME=zookeeper… 0B <missing> 2 months ago /bin/sh -c #(nop) ARG GPG_KEY=3F7A1D16FA421… 0B <missing> 2 months ago /bin/sh -c set -eux; apt-get update; … 12.3MB <missing> 2 months ago /bin/sh -c set -eux; groupadd -r zookeep… 329kB <missing> 2 months ago /bin/sh -c #(nop) ENV ZOO_CONF_DIR=/conf ZO… 0B <missing> 2 months ago /bin/sh -c set -eux; arch="$(dpkg --print-… 109MB <missing> 2 months ago /bin/sh -c #(nop) ENV JAVA_VERSION=8u292 0B <missing> 2 months ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B <missing> 2 months ago /bin/sh -c #(nop) ENV PATH=/usr/local/openj… 0B <missing> 2 months ago /bin/sh -c { echo '#/bin/sh'; echo 'echo "$J… 27B <missing> 2 months ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/local/… 0B <missing> 2 months ago /bin/sh -c set -eux; apt-get update; apt-g… 8.82MB <missing> 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 2 months ago /bin/sh -c #(nop) ADD file:7362e0e50f30ff454… 69.3MB
docker ps 列出本机容器
docker container ls
等于docker ps
docker ps
列出本机正在运行的容器docker ps -a
列出本机所有容器,包括终止运行的容器$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5edb883d9423 nginx:alpine "nginx -g 'daemon of…" 10 months ago Up 10 months nginx e057ebc04ff5 gogs/gogs "/app/gogs/docker/st…" 12 months ago Up 12 months gogs 756930ef3388 search "java -jar /app.jar" 12 months ago Up 12 months search 992185baf34b disqus "java -jar /app.jar" 12 months ago Up 12 months disqus d89f76910cd6 statistic "java -jar /app.jar" 12 months ago Up 12 months statistic 2dcbb37eb434 eureka "java -jar /app.jar" 12 months ago Up 12 months eureka
docker container start 启动已终止容器
可以利用
docker container start
命令,直接将一个已经终止的容器启动运行。docker stop 终止容器
docker container stop
等于docker stop
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker rm 删除容器
docker exec 进入容器执行命令
先查看当前运行的容器
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 724d51cc7cf7 nginx "nginx -g 'daemon of…" 47 minutes ago Up 47 minutes 0.0.0.0:80->80/tcp mystifying_knuth
指定容器id进入容器
$ docker exec -it 724d51cc7cf7 bash root@724d51cc7cf7:/#
OCI runtime exec failed bash executable file not found
原因: 原因是该容器并没有 bash
解决: 改用 shdocker exec -it 33e828194205 sh
docker commit 将容器保存为镜像
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
-a, --author string
指定修改的作者-m, --message string
记录本次修改的内容$ docker commit \ -a "Tao Wang <twang2218@gmail.com>" \ -m "修改了默认网页" \ webserver \ nginx:v2
其中 -a 指定修改的作者,而 -m 则是记录本次修改的内容,这点和 git 版本控制相似,不过这里这些信息可以省略留空。
docker save 导出镜像
https://docs.docker.com/engine/reference/commandline/save/
保存镜像到 tar 文件,默认输出到 stdout, 默认包含所有的 layer, 所有的tags, 当然也可以指定tags
-o, --output
docker save 默认是输出到 stdout, 通过-o
参数可指定保存的档案文件名
docker save busybox > busybox.tar
保存镜像 busybox 的所有版本到 busybox.tar 文件docker save -o myimage.tar myimage:tag1
保存镜像 myimage 的 tag1 版本到 myimage.tar 文件利用 docker save/load 导入导出镜像
方法一、利用 gzip/gunzip 压缩解压
导出镜像并压缩为gzipdocker save myimage:latest | gzip > myimage_latest.tar.gz
导出镜像并压缩倒入镜像压缩包
gunzip -c myimage_tag.tar.gz | docker load
方法二、或者使用 tar 命令压缩和解压
docker save myimage:tag > myap.tar tar -zcvf myap.tar.gz myap.tar
解压导入镜像
tar -xzvf myap.tar.gz docker load < myap.tar
当然,如果 tar 文件本身不大,不用压缩也可以。
内网下载docker镜像
docker load 导入镜像
https://docs.docker.com/engine/reference/commandline/load/
从 tar 文件或标准输入 stdin 导入镜像,会重建镜像和所有的 tag.
这里的 tar 文件是用docker save
命令导出的镜像。--input , -i
: 指定导入的文件,代替 STDIN。--quiet , -q
: 精简输出信息。
docker load < busybox.tar.gz
利用输入重定向从 tar 文件导入镜像docker load --input fedora.tar
通过--input
参数指定 tar 文件导入镜像docker cp 在容器和宿主机间拷贝文件/目录
https://docs.docker.com/engine/reference/commandline/cp/
docker cp
等于docker container cp
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
示例
1、将容器中的文件 /root/123.mp4 拷贝到宿主机的 /root/mp4/ 目录中,其中 335d957237c9 是容器iddocker cp 335d957237c9:/root/123.mp4 /root/mp4/
2、将容器中的 /root/images 目录拷贝到宿主机的 /root/data/ 目录中,其中 335d957237c9 是容器id
docker cp 335d957237c9:/root/images /root/data/
3、将宿主机当前目录中的 xx.mp4 文件拷贝到容器的 /root/data/ 目录中,其中 video-processor 是容器名
docker cp xx.mp4 video-processor:/root/data/
docker tag 重命名镜像
https://docs.docker.com/engine/reference/commandline/tag/
docker tag IMAGE[:TAG] [REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]
重命名镜像,将 source 重命名为 target
docker tag myapp:ver1 myapp:ver2docker logs 查看容器日志
docker inspect 显示容器信息
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
$ docker inspect blog "Id": "1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195", "Created": "2023-08-24T13:24:10.537047009Z", "Path": "java", "Args": [ "-jar", "/blog-server.jar" "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 30211, "ExitCode": 0, "Error": "", "StartedAt": "2023-08-24T13:24:10.735225254Z", "FinishedAt": "0001-01-01T00:00:00Z" "Image": "sha256:8a4f3b90771a63fca73de426a882b9e540cdb3e82bb54f5c6828fdd0fcac7019", "ResolvConfPath": "/var/lib/docker/containers/1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195/resolv.conf", "HostnamePath": "/var/lib/docker/containers/1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195/hostname", "HostsPath": "/var/lib/docker/containers/1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195/hosts", "LogPath": "/var/lib/docker/containers/1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195/1b2a948873a0b44a6553dfee4ab96160195d1d41c10047d08744f9331f370195-json.log", "Name": "/blog", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": [ "/home/centos/git/hexo/source/_posts:/home/centos/git/hexo/source/_posts", "/var/log/spring:/var/log/spring" "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} "NetworkMode": "host", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 "AutoRemove": true, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Capabilities": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/1348860d518c757e7e1ff3c1e6f28c07c19de62d89a7cef4c80ceaad16fe462b-init/diff:/var/lib/docker/overlay2/e8b6a48ed759efa3ae67ecb40263598c0a8b6ee5301462bcc3d83e5e793b1cd2/diff:/var/lib/docker/overlay2/1fa0bf9fa238529796268727234d64c5ae43c0a772777ab5e994e507e0d8941b/diff:/var/lib/docker/overlay2/fe8966ed84314a86ccefe3ba6f82e63e1cf8d26228ac5617e19de5458665a80a/diff:/var/lib/docker/overlay2/02e5f96ab2f2cec701cb9112b46bb70e5f0c9e74e5e2a724209fe877a927ce75/diff:/var/lib/docker/overlay2/1961851b14190d3e33ff7d4da98ebbc6ef15e766381c4d6f33b07b8bfcd640ec/diff:/var/lib/docker/overlay2/71c38e268e4e12d19c1eb6a5f9dac9d368f13e27e38e8cc65fad6d44e0134677/diff:/var/lib/docker/overlay2/a1151919d07928f90f2dfec6cd51f8d481058a9d89a4a85119f6a507ee606f8a/diff:/var/lib/docker/overlay2/bf2ff9aa57906946d9b64e98f7868a098384e9b1eb6a7847dd0b39553be7350e/diff:/var/lib/docker/overlay2/184ccf4335849b0b9d4427c47fed2d4e098fa278841cb3b73b8296a053eb7da2/diff:/var/lib/docker/overlay2/309a7215c73eed1e4362551ef038f89b22fa388289b6bae168eef3d0849e54c8/diff:/var/lib/docker/overlay2/72c8c882fb6eef99e0d0e65c6346123f7e6d518edb5f8a87251dcd1e3d150994/diff", "MergedDir": "/var/lib/docker/overlay2/1348860d518c757e7e1ff3c1e6f28c07c19de62d89a7cef4c80ceaad16fe462b/merged", "UpperDir": "/var/lib/docker/overlay2/1348860d518c757e7e1ff3c1e6f28c07c19de62d89a7cef4c80ceaad16fe462b/diff", "WorkDir": "/var/lib/docker/overlay2/1348860d518c757e7e1ff3c1e6f28c07c19de62d89a7cef4c80ceaad16fe462b/work" "Name": "overlay2" "Mounts": [ "Type": "bind", "Source": "/var/log/spring", "Destination": "/var/log/spring", "Mode": "", "RW": true, "Propagation": "rprivate" "Type": "volume", "Name": "30fc28fdb0150ac58196c22ed7a93859f4f006a6144e45a7ac1debf48d325dc9", "Source": "/var/lib/docker/volumes/30fc28fdb0150ac58196c22ed7a93859f4f006a6144e45a7ac1debf48d325dc9/_data", "Destination": "/tmp", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" "Type": "bind", "Source": "/home/centos/git/hexo/source/_posts", "Destination": "/home/centos/git/hexo/source/_posts", "Mode": "", "RW": true, "Propagation": "rprivate" "Config": { "Hostname": "lightsail", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "SPRING_PROFILES_ACTIVE=prod", "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "LANG=en_US.UTF-8", "LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8", "JAVA_VERSION=jdk8u382-b05", "JAVA_HOME=/opt/java/openjdk", "LD_LIBRARY_PATH=:/usr/lib64" "Cmd": null, "Image": "blog", "Volumes": { "/tmp": {} "WorkingDir": "", "Entrypoint": [ "java", "-jar", "/blog-server.jar" "OnBuild": null, "Labels": { "org.label-schema.build-date": "20201113", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS", "org.opencontainers.image.created": "2020-11-13 00:00:00+00:00", "org.opencontainers.image.licenses": "GPL-2.0-only", "org.opencontainers.image.title": "CentOS Base Image", "org.opencontainers.image.vendor": "CentOS" "NetworkSettings": { "Bridge": "", "SandboxID": "1784dcbf33ad6f4b77cee88b29fd5a20c004ae83314449e6a8e3d65ec4da0432", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/default", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": { "host": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "f2bdcc4e19f4fddcc771e5107d9aeb36e7bdfcd1a2ff93afb3d34da6cbce33b7", "EndpointID": "f27b48b87af78897921f13db8187b4c17756f8d63a0ff51ac292e0372c6ce443", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "", "DriverOpts": null
如何查看容器的启动命令
docker compose
docker-compose
docker / compose
https://github.com/docker/compose安装 docker-compose
1、下载二进制可执行文件,命名为
docker-compose
sudo mv curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose curl -SL https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
2、
sudo chmod +x /usr/local/bin/docker-compose
3、查看版本,有输出就是安装成功
$ docker-compose -v docker-compose version 1.26.2, build eefe0d31
Install Docker Compose
https://docs.docker.com/compose/install/docker-compose.yml配置文件
compose 文件包含了 4 个顶级键:
version:指定文件规范版本
services:指定要操作的容器
networks:指定共用的网络配置
volumes:指定共用的存储配置可以使用 docker-compose config 验证和查看待操作的Compose文件
docker-compose.yml格式版本和docker兼容对照表
Compose and Docker compatibility matrix
https://docs.docker.com/compose/compose-file/depends_on
解决容器的依赖、启动先后的问题。以下例子中会先启动 redis db 再启动 web
version: '3' services: build: . depends_on: - redis redis: image: redis image: postgres
注意:web 服务不会等待 redis db 「完全启动」之后才启动。
docker compose 命令
命令说明 - 《Docker — 从入门到实践》
https://yeasy.gitbook.io/docker_practice/compose/commands指定配置文件
如果你使用默认配置文件名称,不需要显式指定
-f docker-compose.yml
如若需指定配置文件,必须在 docker-compose 后面指定,不能在 up 等子命令后面指定,否则无效;up
-d, --detach
后台启动
默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。
当通过 Ctrl-C 停止命令时,所有容器将会停止。
如果使用docker-compose up -d
,将会在后台启动并运行所有的容器。
--no-recreate
默认情况,如果服务容器已经存在,docker-compose up
将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用docker-compose up --no-recreate
这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果需要的话,这样将会启动已经停止的容器。指定 service
如果用户只想重新部署某个服务,可以使用docker-compose up --no-deps -d <SERVICE_NAME>
来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。链接的服务都将会启动,除非他们已经运行。
start
启动一个已经存在的服务容器。stop
停止一个已经运行的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。
ps
查看容器,在 docker-compose.yml 所在目录中执行
docker-compose ps
只查看此 compose.yml 描述的容器状态# docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------- zookeeper_1 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2181->2181/tcp, 2888/tcp, 3888/tcp zookeeper_2 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2182->2181/tcp, 2888/tcp, 3888/tcp zookeeper_3 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2183->2181/tcp, 2888/tcp, 3888/tcp
当然也可以直接
docker ps
查看所有容器的状态
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 936ca6a90d3f zookeeper:3.4.10 "/docker-entrypoint.…" 27 minutes ago Up 27 minutes 2888/tcp, 0.0.0.0:2181->2181/tcp, 3888/tcp zookeeper_1 475f0ec7ef1b zookeeper:3.4.10 "/docker-entrypoint.…" 27 minutes ago Up 27 minutes 2888/tcp, 3888/tcp, 0.0.0.0:2182->2181/tcp zookeeper_2 d8b28308b6eb zookeeper:3.4.10 "/docker-entrypoint.…" 27 minutes ago Up 27 minutes 2888/tcp, 3888/tcp, 0.0.0.0:2183->2181/tcp zookeeper_3
docker compose 网络
默认情况下,Compose会为我们的应用创建一个网络,服务的每个容器都会加入该网络中。这样,容器就可被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为hostname被其他容器访问。
默认情况下,应用程序的网络名称基于Compose的工程名称,而项目名称基于docker-compose.yml所在目录的名称。如需修改工程名称,可使用–project-name标识或COMPOSE_PORJECT_NAME环境变量。
举个例子,假如一个应用程序在名为myapp的目录中,并且docker-compose.yml如下所示:
version: "3" services: build: . ports: - "8000:8000" image: postgres ports: - "8001:5432"
当我们运行 docker-compose up时,将会执行以下几步:
创建一个名为myapp_default的网络;
使用web服务的配置创建容器,它以“web”这个名称加入网络myapp_default;
使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default。
Networking in Compose
https://docs.docker.com/compose/networking/network_mode使用默认docker网络
network_mode: "host" # 使用主机网络 network_mode: "bridge" network_mode: "none"
network_mode
https://docs.docker.com/compose/compose-file/#network_modedocker仓库
Red Hat
https://quay.io/repository/
https://cloud.google.com/container-registry/docker hub
Docker Hub 是由 Docker 公司负责维护的公共注册中心,包含大量的容器镜像,Docker 工具默认从这个公共镜像库下载镜像。
https://hub.docker.com/推送镜像到 Docker Hub
2、在命令行登录 Docker Hub 账号
$ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: masikkk Password: WARNING! Your password will be stored unencrypted in /home/centos/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
3、查看本地镜像
# 查看本地镜像 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE masikkk/centos7-openjdk21 20240123 5996f993958f 7 weeks ago 720MB masikkk/centos7-openjdk21-tesseract 20240123 15a6611140d7 40 hours ago 1.07GB
打镜像 tag 时需要注意名称中必须包含 Docker Hub 账号,我的账号是 masikkk,则镜像必须是
masikkk/
开头,否则推送到 Docker Hub 时报错:
[centos@lightsail ~]$ docker push centos7-openjdk21 The push refers to repository [docker.io/library/centos7-openjdk21] 9441bde1b4e1: Preparing 0256674c5104: Preparing 174f56854903: Preparing denied: requested access to the resource is denied
4、推送镜像到 Docker Hub
$ docker push masikkk/centos7-openjdk21:20240123 The push refers to repository [docker.io/masikkk/centos7-openjdk21] 9441bde1b4e1: Pushed 0256674c5104: Pushed 174f56854903: Pushed 20240123: digest: sha256:4707f90e6f702881dacd53a5480c129b8aca4baef6f6d2615a8243bda965d45d size: 954
Push the image
https://docs.docker.com/get-started/04_sharing_app/#push-the-imagedocker-registry 私人仓库
$ docker run -d \ -p 5000:5000 \ --restart=always \ --name registry \ -v /home/centos/docker/registry:/var/lib/registry \ registry
nvidia-docker
NVIDIA / nvidia-docker
https://github.com/NVIDIA/nvidia-dockernvidia-docker 相关组件
nvidia-docker2
nvidia-container-runtime
nvidia-container-toolkit
libnvidia-container
之间的关系What’s the difference between the lastest nvidia-docker and nvidia container runtime? #1268
https://github.com/NVIDIA/nvidia-docker/issues/1268crane 镜像工具
crane 是一个与远程镜像和仓库交互的工具,由 Google containerregistry 开发
安装
# go 安装 go install github.com/google/go-containerregistry/cmd/crane@latest # Mac brew install crane # bin https://github.com/google/go-containerregistry/releases
命令
https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane.md
如果镜像仓库开启了用户认证,需要在使用之前先通过 crane auth login 登录:
crane auth login localhost:5000 -u admin -p passw0rd将本地镜像内容推送到远程仓库
crane –insecure push myapp-1.2.1.tar localhost:5000/myapp:1.2.1搭建自己的镜像仓库
https://www.aneasystone.com/archives/2022/09/build-your-own-image-registry.html实践
busybox 镜像
BusyBox 是一个集成了一百多个最常用 Linux 命令和工具(如 cat、echo、grep、mount、telnet 等)的精简工具箱,它只需要几 MB 的大小,很方便进行各种快速验证。
hexo镜像
docker run -d -it --rm \ -v ~/.ssh:/home/centos/.ssh \ masikkk/centos7-openjdk21-node16-hexo7:20240317 bash
后台启动容器,然后
docker exec
进入容器
根据 https://github.com/nodesource/distributions/tree/master?tab=readme-ov-file#rpm-supported-versions CentOS7最高只支持 nodejs 17,18及之上版本需要 CentOS8
安装git
sudo yum install -y gitgit clone git@github.com:masikkk/hexo.git
安装 nodejs 17
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash - sudo yum install -y nodejs # node -v v17.9.0 # npm -v 8.5.5
Centos7-OpenJDK 镜像
nimmis/centos7-openjdk8 镜像
nimmis/java-centos
https://hub.docker.com/r/nimmis/java-centos/tags?page=1&name=openjdk-8Dockerfile
https://github.com/nimmis/docker-java-centos/blob/master/openjdk-8-jdk/Dockerfile只有amd64架构的
docker pull nimmis/java-centos:openjdk-8-jdk REPOSITORY TAG IMAGE ID CREATED SIZE nimmis/java-centos openjdk-8-jdk 8a93794b15b0 5 years ago 402MB
AdoptOpenJDK/centos7-openjdk8 镜像
adoptopenjdk/openjdk8
https://hub.docker.com/r/adoptopenjdk/openjdk8/tags?page=1&name=centosDockerfile 文件
https://github.com/AdoptOpenJDK/openjdk-docker/blob/master/8/jdk/centos/Dockerfile.hotspot.releases.fullAdoptOpenJDK 已被官方废弃,最高只到 jdk16
注意此镜像有多种架构,M1 Mac 上默认会拉取 arm64 架构的版本,如果想要使用 amd64/x86_64 架构版本,需要通过--platform amd64
参数指定docker pull adoptopenjdk/openjdk8:centos –platform amd64
docker pull adoptopenjdk/openjdk8:centos-slim –platform amd64REPOSITORY TAG IMAGE ID CREATED SIZE
adoptopenjdk/openjdk8 centos-slim f7719a74b210 17 hours ago 471MB
adoptopenjdk/openjdk8 centos a72f04e4db6d 17 hours ago 579MB自己构建 Centos7-OpenJDK8 镜像
1、创建 centos7-openjdk8.Dockerfile
FROM centos:7 MAINTAINER masikkk.com RUN yum update -y && \ yum install -y wget && \ yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel && \ yum clean all # Set environment variables. ENV HOME /root # Define working directory. WORKDIR /root # Define default command. CMD ["java","-version"]
2、构建镜像
进入 centos7-openjdk8.Dockerfile 文件所在目录docker build -f centos7-openjdk8.Dockerfile -t masikkk/centos7-openjdk8:20240123 .
结果
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE masikkk/centos7-openjdk8 20240123 a44b575730c8 56 seconds ago 602MB
3、运行镜像,由于 Dockerfile 里的 CMD 命令就是
java -version
,执行docker run
可直接看到 java 版本
$ docker run masikkk/centos7-openjdk8:20240123 openjdk version "1.8.0_392" OpenJDK Runtime Environment (build 1.8.0_392-b08) OpenJDK 64-Bit Server VM (build 25.392-b08, mixed mode)
也可以执行
docker run -it --rm centos7-openjdk8:20240123 bash
进入镜像看看 java 版本4、推送到 Docker Hub
$ docker push masikkk/centos7-openjdk8:20240123 The push refers to repository [docker.io/masikkk/centos7-openjdk8] ceb11fb82205: Pushed 174f56854903: Mounted from masikkk/centos7-openjdk21-tesseract 20240123: digest: sha256:93b85206411b507e869aeb841118b9bb23db26f53d3979a70c2f957b39fd244c size: 742
镜像已发布到 Docker Hub 公开仓库,可直接使用
https://hub.docker.com/repository/docker/masikkk/centos7-openjdk8自己构建 CentOS7-OpenJDK21 镜像
1、创建 centos7-openjdk21.Dockerfile
# 自己基于CentOS7构建带JDK8的镜像 FROM centos:7 MAINTAINER masikkk.com # 更新yum,安装wget RUN yum update -y && \ yum install -y wget && \ yum clean all # https://jdk.java.net/21/ RUN mkdir -p /opt/java && \ cd /opt/java && \ wget https://download.java.net/java/GA/jdk21.0.1/415e3f918a1f4062a0074a2794853d0d/12/GPL/openjdk-21.0.1_linux-x64_bin.tar.gz && \ tar -xf openjdk-21.0.1_linux-x64_bin.tar.gz && \ rm -rf openjdk-21.0.1_linux-x64_bin.tar.gz # Set environment variables. ENV JAVA_HOME /opt/java/jdk-21.0.1 ENV PATH $PATH:$JAVA_HOME/bin # Define default command. CMD ["java","-version"]
2、进入 centos7-openjdk21.Dockerfile 所在目录,执行:
docker build -f centos7-openjdk21.Dockerfile -t masikkk/centos7-openjdk21:20240123 .
$ docker images REPOSITORY TAG IMAGE ID CREATED masikkk/centos7-openjdk21 20240123 5996f993958f 7 weeks ago 720MB
3、执行
docker run masikkk/centos7-openjdk21:20240123
验证,由于 Dockerfile 里的 CMD 命令就是java -version
,docker run
可直接看到 java 版本
$ docker run masikkk/centos7-openjdk21:20240123 openjdk version "21.0.1" 2023-10-17 OpenJDK Runtime Environment (build 21.0.1+12-29) OpenJDK 64-Bit Server VM (build 21.0.1+12-29, mixed mode, sharing)
也可以
docker run -it --rm masikkk/centos7-openjdk21:20240123 bash
进入容器验证
或者docker run -d -it --rm masikkk/centos7-openjdk21:20240123 bash
后台启动容器,然后docker exec
进入容器。4、推送到 Docker Hub
$ docker push masikkk/centos7-openjdk21:20240123 The push refers to repository [docker.io/masikkk/centos7-openjdk21] 9441bde1b4e1: Pushed 0256674c5104: Pushed 174f56854903: Pushed 20240123: digest: sha256:4707f90e6f702881dacd53a5480c129b8aca4baef6f6d2615a8243bda965d45d size: 954
镜像已发布到 Docker Hub 公开仓库,可直接使用
https://hub.docker.com/repository/docker/masikkk/centos7-openjdk21/general自己构建 CentOS7-OpenJDK21-tesseract 镜像
1、创建 centos7-openjdk21-tesseract.Dockerfile
# 基于自己构建的 Centos7-OpenJDK21 镜像 FROM masikkk/centos7-openjdk21:20240123 MAINTAINER masikkk.com # 更新yum,安装wget RUN yum update -y && \ yum install -y wget && \ yum clean all # 安装 tesseract,加 --nogpgcheck 忽略公钥检查 RUN yum-config-manager --add-repo http://download.opensuse.org/repositories/home:/Alexander_Pozdnyakov/RHEL_7/ && \ yum update -y && \ yum install tesseract -y --nogpgcheck # 容器默认命令 CMD ["tesseract","-v"]
2、进入 centos7-openjdk21-tesseract.Dockerfile 所在目录,执行:
docker build -f centos7-openjdk21-tesseract.Dockerfile -t masikkk/centos7-openjdk21-tesseract:20240123 .
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE masikkk/centos7-openjdk21-tesseract 20240123 15a6611140d7 40 hours ago 1.07GB
3、执行
docker run masikkk/centos7-openjdk21-tesseract:20240123
由于 CMD 默认命令是tesseract -v
,可直接看到 tesseract 版本号:
$ docker run masikkk/centos7-openjdk21-tesseract:20240123 tesseract 4.1.3 leptonica-1.76.0 libjpeg 6b (libjpeg-turbo 1.2.90) : libpng 1.5.13 : libtiff 4.0.3 : zlib 1.2.7 : libwebp 0.3.0 Found AVX2 Found AVX Found FMA Found SSE
也可以
docker run -it --rm masikkk/centos7-openjdk21-tesseract:20240123 bash
进入容器验证。4、推送到 Docker Hub
$ docker push masikkk/centos7-openjdk21-tesseract:20240123 The push refers to repository [docker.io/masikkk/centos7-openjdk21-tesseract] 0dcffa355b31: Pushed ce751aba1cc4: Pushed 9441bde1b4e1: Mounted from masikkk/centos7-openjdk21 0256674c5104: Mounted from masikkk/centos7-openjdk21 174f56854903: Mounted from masikkk/centos7-openjdk21 20240123: digest: sha256:cf72104eac31f86e2a082d7c13205ef697b5bddd841c3ab27823b1078d3420ce size: 1379
镜像已发布到 Docker Hub 公开仓库,可直接使用
https://hub.docker.com/repository/docker/masikkk/centos7-openjdk21-tesseract/generalDocker 构建部署 SpringBoot 服务
Spring Boot with Docker
https://spring.io/guides/gs/spring-boot-docker/docker hub / openjdk
https://hub.docker.com/_/openjdk构建基于 openjdk:8-alpine 的 SpringBoot 服务镜像
FROM openjdk:8-jdk-alpine VOLUME /tmp ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar RUN apk add --no-cache tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/shanghai" > /etc/timezone \ && rm -rf /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cache ## 清除缓存 ENTRYPOINT ["java","-jar","/app.jar"]
由于 alpine 中是 UTC 时区,需要改为东八区,但 alpine 中默认又没有
/usr/share/zoneinfo/Asia/Shanghai
时区文件,只能先安装时区文件 tzdata,再链接到 /etc/localtime2、先用 maven 把 spring boot 项目打包为可运行的 jar 包
mvn package
3、构建 SpringBoot Docker 镜像
在 Dockerfile 所在的项目根目录下 构建镜像docker build -t blog-server .
注意一定要在 Dockerfile 所在的目录,最后那个.
指定了当前目录是构建上下文。
$ docker build -t blog-server . Sending build context to Docker daemon 117.6MB Step 1/6 : FROM openjdk:8-jdk-alpine ---> a3562aa0b991 Step 2/6 : VOLUME /tmp ---> Using cache ---> d0ee8c49a7f7 Step 3/6 : ARG JAR_FILE=target/*.jar ---> Using cache ---> 8db784deccb1 Step 4/6 : COPY ${JAR_FILE} app.jar ---> 506e8cf80e06 Step 5/6 : RUN apk add --no-cache tzdata && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/shanghai" > /etc/timezone && rm -rf /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cache ## 清除缓存 ---> Running in 74f8c63c1c21 fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz (1/1) Installing tzdata (2020c-r1) Executing busybox-1.29.3-r10.trigger OK: 107 MiB in 55 packages Removing intermediate container 74f8c63c1c21 ---> 8686579ddbe7 Step 6/6 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in acacc24c7c34 Removing intermediate container acacc24c7c34 ---> b6c2b7ac458f Successfully built b6c2b7ac458f Successfully tagged blog-server:latest
4、查看构建好的镜像
docker images
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE blog-server latest b6c2b7ac458f 37 seconds ago 224MB
构建基于 centos7-openjdk8 的 SpringBoot 服务镜像
# https://hub.docker.com/r/adoptopenjdk/openjdk8/tags?page=1&name=centos # https://github.com/AdoptOpenJDK/openjdk-docker/blob/master/8/jdk/centos/Dockerfile.hotspot.releases.full FROM adoptopenjdk/openjdk8:centos VOLUME /tmp MAINTAINER masikkk.com RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ARG JAR_FILE=blog-server/target/blog-server.jar COPY ${JAR_FILE} /blog-server.jar ENTRYPOINT ["java","-jar","/blog-server.jar"]
2、构建镜像
我在 M1 Mac 上默认会构建 “Architecture”: “arm64” 架构的镜像,为了能在 Linux 上复用,通过--platform=amd64
指定构建 amd64/x86_64 架构的镜像
docker build -f blog.Dockerfile –platform=amd64 -t blog .
启动 SpringBoot Docker 容器
linux 中启动 SpringBoot Docker 容器
docker run -d --rm \ --network host \ --name blog-server \ -v /var/log/spring:/var/log/spring \ -e "SPRING_PROFILES_ACTIVE=local" \ blog-server
以 host 网络模式启动容器,和宿主机完全共享网络,不需要再配置 -p
端口映射我的业务日志写到了 /data/log/spring 目录中,通过 -v
映射到本地-e "SPRING_PROFILES_ACTIVE=local"
指定启动spring的profile启动后进入容器
docker exec -it blog-server sh
查看系统版本
# cat os-release NAME="Alpine Linux" ID=alpine VERSION_ID=3.9.4 PRETTY_NAME="Alpine Linux v3.9" HOME_URL="https://alpinelinux.org/" BUG_REPORT_URL="https://bugs.alpinelinux.org/"
Mac 上启动 SpringBoot Docker 容器
Mac 上启动,由于 mac 中没有 host 网络,需要 -p 指定端口映射
docker run -d --rm \ -p 8001:8001 \ --name blog \ -v /var/log/spring:/var/log/spring \ -e "SPRING_PROFILES_ACTIVE=local" \
M1 Mac 上运行 amd64/x86_64 架构镜像
docker run -d --rm \ --platform linux/amd64 \ -p 8001:8001 \ --name blog \ -v /var/log/spring:/var/log/spring \ -e "SPRING_PROFILES_ACTIVE=local" \
Docker 容器部署 Nginx
docker hub 的 nginx 官方页面里有比较全面的用法
https://hub.docker.com/_/nginxNginx 容器教程
https://www.ruanyifeng.com/blog/2018/02/nginx-docker.html拉取最新 alpine 版本 Nginx 镜像
拉取官方 nginx alpine 版本镜像的最新版
docker pull nginx:alpine
$ docker pull nginx:alpine alpine: Pulling from library/nginx 4167d3e14976: Pull complete bb292c78f105: Pull complete Digest: sha256:abe5ce652eb78d9c793df34453fddde12bb4d93d9fbf2c363d0992726e4d2cad Status: Downloaded newer image for nginx:alpine docker.io/library/nginx:alpine
启动默认 nginx:alpine 镜像
进容器中查看系统版本
查看/etc/os-release
文件# cat /etc/os-release NAME="Alpine Linux" ID=alpine VERSION_ID=3.10.4 PRETTY_NAME="Alpine Linux v3.10" HOME_URL="https://alpinelinux.org/" BUG_REPORT_URL="https://bugs.alpinelinux.org/"
nginx 版本
# nginx -v nginx version: nginx/1.17.9
配置目录
/etc/nginx/nginx.conf
日志目录
/var/log/nginx/error.log
/var/log/nginx/access.log
指定配置文件启动 nginx:alpine
还使用原始的 nginx:alpine 官方镜像,只不过在启动命令中加入自己的配置,很方便
aws 上的nginx
docker run -d --rm \ --network host \ --name nginx \ -e TZ="Asia/Shanghai" \ -v /home/centos/git/hexo/nginx/nginx-centos.conf:/etc/nginx/nginx.conf:ro \ -v /home/centos/git/hexo/public:/home/centos/git/hexo/public \ -v /home/centos/git/image:/home/centos/git/image \ -v /var/log/nginx:/var/log/nginx \ nginx:alpine
以 host 网络模式启动容器,和宿主机完全共享网络,不需要再配置 -p
端口映射,否则容器内的 nginx 需要配置主机 ip 才能访问主机网络。容器中默认是 UTC 时区,比我们的时间慢8小时,改为 Asia/Shanghai 即东八区 文件和文件夹映射 把本地的 nginx 配置文件 /home/centos/git/hexo/nginx/nginx-centos.conf 映射到容器中的 /etc/nginx/nginx.conf,会自动覆盖容器的配置文件,注意必须用绝对路径。这两个文件可以不同名。 把静态文件目录 /home/centos/git/hexo/public 映射到容器中的同名目录,由于容器中没有这个目录,会自动新建并将全部内容拷贝进去,而且,以后宿主机此文件夹的更新会完全反应到容器中。 把图片文件目录 /home/centos/git/hexo/image 映射到容器中的同名目录,由于容器中没有这个目录,会自动新建并将全部内容拷贝进去,而且,以后宿主机此文件夹的更新会完全反应到容器中。 把容器中 nginx 的日志目录 /var/log/nginx 映射到本机的同名目录,由于本机没有 /var/log/nginx 目录,会自动创建,之后在本机即可看 nginx 日志 --rm
表示停止容器时删除容器文件,因为 nginx 是无状态的即开即用服务,且配置文件和静态文件映射自宿主机文件,容器内不需要任何持久化,停止后删掉就行,下次再重新启动一个新容器。--name nginx
指定一个容器名,方便之后的操作
构建自己的 nginx 镜像并启动
在 nginx-centos.conf 文件所在的目录中新建 Dockerfile 文件
FROM nginx:alpine COPY nginx-centos.conf /etc/nginx/nginx.conf RUN echo "Asia/shanghai" > /etc/timezone \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
基础镜像是 alpine 版本最新 nginx 把自己的配置文件 nginx-centos.conf 拷贝到容器中覆盖默认的 /etc/nginx/nginx.conf 修改容器的时区 在 Dockerfile 所在目录内执行
docker build -t nginx-masikkk .
构建自己的 nginx 镜像,名为 nginx-masikkk, 以当前路径为上下文路径
一定要注意上下文路径是当前所在文件夹,所以COPY
指令才可以直接拷贝当前文件夹中的 nginx-centos.conf 文件
$ docker build -t nginx-masikkk . Sending build context to Docker daemon 15.87kB Step 1/3 : FROM nginx latest: Pulling from library/nginx Digest: sha256:50cf965a6e08ec5784009d0fccb380fc479826b6e0e65684d9879170a9df8566 Status: Downloaded newer image for nginx:latest ---> 231d40e811cd Step 2/3 : COPY nginx-centos.conf /etc/nginx/nginx.conf ---> e45c37eea53f Step 3/3 : RUN echo "Asia/shanghai" > /etc/timezone && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ---> Running in f8cc0a26834a Removing intermediate container f8cc0a26834a ---> 20ad396f30ea Successfully built 20ad396f30ea Successfully tagged nginx-masikkk:latest
查看构建好的镜像
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE nginx-masikkk latest 20ad396f30ea 4 seconds ago 126MB nginx latest 231d40e811cd 4 weeks ago 126MB
启动自己的 nginx 容器
docker run -d --rm \ --network host \ --name nginx \ -v /home/centos/git/hexo/public:/home/centos/git/hexo/public \ -v /home/centos/git/hexo/image:/home/centos/git/hexo/image \ -v /var/log/nginx:/var/log/nginx \ nginx-masikkk
这样启动命令可以少两个参数。
nginx.conf 中的用户名必须是 nginx
docker容器部署prometheus
INSTALLATION
https://prometheus.io/docs/prometheus/latest/installation/docker 太方便了,准备好配置文件后直接启动就行,自动从 dockerhub 拉取最新官方镜像
我的启动命令如下:docker run -d --rm \ --network host \ --name prometheus \ -v /home/centos/git/masikkk/prometheus.yml:/etc/prometheus/prometheus.yml \ prom/prometheus
解释下:
-d
后台运行--rm
停止容器后删掉容器文件--network host
与宿主机完全共享网络,默认是bridge桥接,无法在nginx中通过localhost转发请求--name grafana
指定启动的容器名,方便按名称stop等操作-v
映射配置文件,具体说是宿主机配置文件覆盖容器中的配置文件,我的配置文件在 git 仓库中,方便保存,也可以记录修改历史。参考笔记 Prometheus
docker容器部署grafana
Installing Grafana
https://grafana.com/docs/grafana/latest/installation/Installing using Docker
https://grafana.com/docs/grafana/latest/installation/docker/第一次执行时直接从 dockerhub 拉取最新版本 grafana
docker run -d --rm \ --network host \ --name grafana \ grafana/grafana
解释下:
-d
后台运行--rm
停止容器后删掉容器文件--network host
与宿主机完全共享网络,默认是bridge桥接,无法在nginx中通过localhost转发请求--name grafana
指定启动的容器名,方便按名称stop等操作参考笔记 Grafana
docker容器部署邮件服务器
tomav/docker-mailserver
https://github.com/tomav/docker-mailservertvial/docker-mailserver
https://hub.docker.com/r/tvial/docker-mailserver利用Docker自建多功能加密邮件服务器
https://www.itmanbu.com/docker-mail-server.htmlMail Server Docker
https://blog.liyang.info/2018/04/17/mail-server-docker/遇到的问题
容器内的nginx无法访问宿主机网络
我在宿主机上用 nodejs 起了个 http 服务器做 git webhooks,监听 1121 端口,在容器内的 nginx 要把访问 1121 端口的请求转发到宿主机上,是这么写的配置
# webhooks.开头的三级域名访问, git的webhooks, 转发到后台 node.js web服务 server { listen 80; server_name webhooks.devgou.com webhooks.madaimeng.com webhooks.masikkk.com; location / { proxy_pass http://localhost:1121;
访问 webhooks 接口的时候报错 502 Bad Gateway, nginx 日志报错
2019/12/25 10:52:31 [error] 6#6: *1892 connect() failed (111: Connection refused) while connecting to upstream, client: 220.194.45.154, server: webhooks.devgou.com, request: "GET /pull/hexo HTTP/1.1", upstream: "http://127.0.0.1:1121/pull/hexo", host: "webhooks.devgou.com" 220.194.45.154 - - [25/Dec/2019:10:52:31 +0800] "GET /pull/hexo HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36" "-" 2019/12/25 10:52:32 [error] 6#6: *1892 no live upstreams while connecting to upstream, client: 220.194.45.154, server: webhooks.devgou.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://localhost/favicon.ico", host: "webhooks.devgou.com", referrer: "http://webhooks.devgou.com/pull/hexo"
也就是找不到 localhost:1121 服务,想了想也是, 容器和宿主机是两个系统,容器的 localhost 和宿主机不同,肯定找不到这个服务。
下面就是解决如何在容器中访问宿主机的网络了方法一,bridge网络模式的容器使用宿主机在docker0网卡上的ip访问宿主机。
安装 Docker 的时候,会在宿主机安装一个虚拟网卡 docker0, 它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
在宿主机上ifconfig
查看 docker0 网卡的ip地址,Linux下一般是 172.17.0.1 , macOS下一般是 192.168.65.1,并不固定。
在容器中使用宿主机ip访问的问题是,配置写死ip非常不灵活,和docker anywhere deploy 的原则相悖。方法二,使用host宿主机网络模式启动容器
Docker容器运行的时候有 host 、 bridge 、 none 三种网络可供配置。默认是 bridge ,即桥接网络,以桥接模式连接到宿主机; host 是宿主网络,即与宿主机共用网络; none 则表示无网络,容器将无法联网。当容器使用 host 网络时,容器与宿主共用网络,这样就能在容器中访问宿主机网络,那么容器的 localhost 就是宿主机的 localhost 。
启动容器时加参数--network host
表示已宿主机网络模式启动容器。此时不需要-p 80:80
做端口映射了,因为本身与宿主机共用了网络,容器中暴露端口等同于宿主机暴露端口。
这种模式的问题是破坏了容器之间的隔离性,好处是网络访问很方便。
Docker容器访问宿主机网络的方法
https://m.jb51.net/article/149173.htm查看容器中的日志
2、启动容器时
-v /var/log/nginx:/var/log/nginx
将容器内日志目录映射到本机,之后直接在本机即可看日志。alpine镜像中jvm工具不可用问题
在alpine镜像中使用诸如jstack,jinfo工具,有如下报错:
1: Unable to get pid of LinuxThreads manager thread原因是pid为1,发现PID为1的时候,工具不可用。
解决:
1、Dockerfile里使用如下命令启动:CMD ["/bin/sh","-c","java APP","&& 1"]
2、或者使用--init
参数来启动dockerjava.lang.UnsatisfiedLinkError: no fontmanager in java.library.path
某些需要绘制图表的 java 应用在 docker 中可能遇到这个问题,比如需要创建 excel 表格的,原因是缺少字体配置。
no fontmanager in java.library.path
https://stackoverflow.com/questions/37251309/no-fontmanager-in-java-library-path/39861372java.lang.UnsatisfiedLinkError: no fontmanager in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at sun.font.FontManagerNativeLibrary$1.run(FontManagerNativeLibrary.java:61) at java.security.AccessController.doPrivileged(Native Method) at sun.font.FontManagerNativeLibrary.<clinit>(FontManagerNativeLibrary.java:32) at sun.font.SunFontManager$1.run(SunFontManager.java:339) at java.security.AccessController.doPrivileged(Native Method) at sun.font.SunFontManager.<clinit>(SunFontManager.java:335)
修改容器时区
可以进入容器修改时区,不推荐
docker exec -it <CONTAINER NAME> bash
echo "Asia/Shanghai" > /etc/timezone
启动容器时用环境变量
TZ
指定时区docker run -e TZ="Asia/Shanghai" -d -p 80:80 --name nginx nginx
启动容器时-v绑定主机时区文件
利用 volume 可以在启动一个 container 时指定使用主机的时区文件,就可以把 container 的时区与主机同步docker run -v /etc/localtime:/etc/localtime <IMAGE:TAG>
Dockerfile中指定时区
RUN echo "Asia/shanghai" > /etc/timezone \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
前提是容器的linux中本身就有
/usr/share/zoneinfo/Asia/Shanghai
时区文件
基于alpine的镜像中修改时区
RUN apk add --no-cache tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/shanghai" > /etc/timezone \ && rm -rf /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cache ## 清除缓存
Mac中使用docker时遇到的问题
mac中映射的文件需要先设置共享
Mac docker 中启动时报错
docker: Error response from daemon: Mounts denied:
The path /var/log/spring
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences… -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.因为通过
-v
映射了一个不在共享配置中的文件夹Mac 系统中想要和容器共享文件夹的话,需要先配置
默认已共享了 /Users/, /Volumes/, /private/, and /tmp
可在 Preferences -> File sharing 中增加共享目录mac上宿主机和容器互相网络访问
mac中没有docker0虚拟网卡
受限于 Docker Desktop for Mac 底层的网络实现, Mac上的docker没有 docker0 网卡。从容器中访问mac网络的方法
通过调试用DNShost.docker.internal
从mac上访问容器网络的方法:
使用-p 80:80
暴露端口,--network host
不起作用host 类型网络只能在 Linux 上使用, 在 Mac 和 Windows 上不支持。
https://docs.docker.com/network/host/
The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.https://docs.docker.com/docker-for-mac/networking/
M1 Mac 上构建和运行 amd64/x86_64 架构镜像
为了在 M1 Mac 上模拟运行 amd64/x86_64 架构的 Linux 环境,需要构建和运行 amd64/x86_64 架构镜像。
1、M1 Mac 上构建 amd64/x86_64 架构镜像
docker build -f devops/blog.Dockerfile –platform=amd64 -t blog .2、M1 Mac 上运行 amd64/x86_64 架构镜像,可以指定
--platform linux/amd64
参数docker run -d --rm \ --platform linux/amd64 \ -p 8001:8001 \ --name blog \ -v /var/log/spring:/var/log/spring \ -e "SPRING_PROFILES_ACTIVE=local" \
如果镜像本身是 amd64/x86_64 架构的,不需要指定,但 docker run 会报警告:
WARNING: The requested image’s platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
- 基本概念
- 安装Docker
- Dockerfile
- Docker API
- Docker 常用命令
- docker info 查看docker信息
- docker system df 查看docker磁盘占用
- docker system prune 系统清理
- docker image prune -a 清理悬空镜像
- docker search
- docker network
- docker run 运行容器
- docker push 推镜像
- docker image inspect 查看镜像详细信息
- docker manifest inspect 查看镜像的manifest列表
- docker pull 下载镜像
- docker images 列出本机镜像
- docker image rm 删除本地镜像
- docker build 构建镜像
- docker history 查看镜像历史
- docker ps 列出本机容器
- docker container start 启动已终止容器
- docker stop 终止容器
- docker rm 删除容器
- docker exec 进入容器执行命令
- docker commit 将容器保存为镜像
- docker save 导出镜像
- docker load 导入镜像
- docker cp 在容器和宿主机间拷贝文件/目录
- docker tag 重命名镜像
- docker logs 查看容器日志
- docker inspect 显示容器信息
- docker compose
- docker-compose
- docker仓库
- nvidia-docker
- crane 镜像工具
- 实践
![]() |
俊秀的滑板 · 中南大学 liuhui 7 月前 |