Docker

Docker是一个跨平台、可移植并且简单易用的容器解决方案。基于Go语言开发。Docker可在容器内部快速自动化地部署应用,并通过操作系统内核技术(namespaces、cgroup等)为容器提供资源隔离和安全保障。

containerd是一个工业级标准的容器运行时,可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。containerd是从docker中分离出来的,或者说containerd本身是docker的一部分。

containerd并不是直接面向最终用户的,而是主要用于集成到更上层的系统里,比如Swarm,Kubernetes,Mesos等容器编排系统。containerd以Daemon的形式运行在系统上,通过unixdomainsocket暴露很底层的gRPCAPI,上层系统可以通过这些API管理机器上的容器。每个containerd只负责一台机器,Pull镜像,对容器的操作(启动、停止等),网络,存储都是由containerd完成。具体运行容器由runC负责,实际上只要是符合OCI规范的容器都可以支持。

一方面应用包含多种服务,这些服务有自己所依赖的库和软件包;另一方面存在多种部署环境,服务在运行时可能需要动态迁移到不同环境中。这就产生了一个问题:如何让每种服务能够在所有的部署环境中顺利进行?各种服务与环境排列组合产生了一个大矩阵,开发人员需要考虑不同的运行环境,运维人员需要为不同的服务和平台配置环境。这对双方而言,都是一项艰难的任务。如何解决这个问题呢?

最终程序员们从传统运输业找到了答案。

集装箱的发明解决这个难题。任何货物,无论钢琴还是保时捷,都被放到各自的集装箱中。集装箱在整个运输过程中都是密封的,只有到达最终目的地才被打开。标准集装箱可以被高效地装卸、重叠和长途运输。现代化的起重机可以自动在卡车、轮船和火车之间移动集装箱。集装箱被誉为运输业与世界贸易最重要的发明。

Docker将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,DockerRegistry就是这样的服务。

一个DockerRegistry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过仓库名:标签的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。

以Ubuntu镜像为例,ubuntu是仓库的名字,其内包含有不同的版本标签,如,16.04,18.04。我们可以通过ubuntu:16.04,或者ubuntu:18.04来具体指定所需哪个版本的镜像。如果忽略了标签,比如ubuntu,那将视为ubuntu:latest

Docker的镜像概念类似于虚拟机里的镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。docker镜像是一个只读的docker容器模板,它含有启动docker容器所需的文件系统结构及内容,是启动一个docker容器的基础。镜像(Image)是Docker最突出的创新。

镜像是容器的基础,每次执行dockerrun的时候都会指定哪个镜像作为容器运行的基础。

docker镜像的文件内容以及一些运行docker容器的配置文件组成了docker容器的静态文件系统运行环境———rootfs。

rootfs是docker容器在启动时内部进程可见的文件系统,即docker容器的根目录。rootfs通常包含一个操作系统运行时所需的文件系统。

在传统的linux操作系统内核启动时,首先挂载一个只读的rootfs,当系统检测其完整性以后,再将其切换为读写模式。在dockerdaemon为docker容器挂载rootfs时,沿用了上述方法,即将rootfs设为只读模式,挂载完毕后,利用联合挂载(unionmount)技术在已有的只读rootfs上在挂载一个读写层。

镜像的特点:分层:docker镜像是采用分层方式构建的,每个镜像都由一系列的“镜像层”组成写时复制:每个容器启动时不需要单独复制一份镜像文件,而是将所有镜像层以只读的方式挂载到一个挂载点,在其上覆盖一个可读写的容器层。内容寻址:对镜像内容计算校验和,生成内容哈希,减少冲突。联合挂载:联合挂载技术可以在一个挂载点同时挂载多个文件系统,将挂载点的原目录与被挂载的内容进行整合,使得最终可见的文件系统将会包含整合之后的各层的文件和目录。

将一个镜像导出为tar文件再解压后,其中的文件如下

$dockersave-ohello-world.tarhello-world:latest$tar-xvfhello-world.tar-Chello-world-imagecdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/cdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/VERSIONcdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/jsoncdccdf50922d90e847e097347de49119be0f17c18b4a2d98da9919fa5884479d/layer.tarfce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e.jsonmanifest.jsonrepositories1、manifest.json清单(manifest)文件是一段元数据,描述了该镜像中的内容。

3、此外有好多子目录,每个子目录是文件系统的一层(layer),每个子目录里也有一个json描述当前层的元数据信息。

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。容器是一个运行的镜像实例,可以创建、启动、终止、删除它。一个容器可以连接多个网络和存储。删除容器后,任何未在存储中进行的修改都会消失。可以这样理解,dockerimage是dockercontainer的静态视角,dockercontainer是dockerimage的运行方式。

UnionFileSystem,简称UnionFS,是一种为Linux,FreeBSD,和NetBSD操作系统设计的把其他文件系统联合挂载到一个挂载点的文件系统服务。它通过使用branch把不同文件系统的文件和目录覆盖,形成一个一致的文件系统。这些branch是只读或者只写的。当对文件进行写操作时候,才会真正的复制文件进行写操作。实际上本身没有对原来的文件进行修改,可以看做是共享了原来的文件。在写的时候进行修改用到了一种资源管理技术成为写时复制。

联合文件系统(UnionFileSystem):2004年由纽约州立大学石溪分校开发,它可以把多个目录(也叫分支)内容联合挂载到同一个目录下,而目录的物理位置是分开的。UnionFS允许只读和可读写目录并存,就是说可同时删除和增加内容。UnionFS应用的地方很多,比如在多个磁盘分区上合并不同文件系统的主目录,或把几张CD光盘合并成一个统一的光盘目录(归档)。另外,具有写时复制(copy-on-write)功能UnionFS可以把只读和可读写文件系统合并在一起,虚拟上允许只读文件系统的修改可以保存到可写文件系统当中。

Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(uniteseveraldirectoriesintoasinglevirtualfilesystem)。

AUFS的英文全称为AdvancedMult-LayeredUnificationFilesystem,之前叫AnotherMult-LayeredUnificationFilesystem

AUFS(AnotherUnionFS)就是一种UnionFS。AUFS支持为每一个成员目录(类似Git的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限,同时AUFS里有一个类似分层的概念,对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。

OverlayFS是和AUFS相似的联合文件系统(unionfilesystem),它有如下特点:设计简洁;内核3.18开始已经并入内核主线可能更快

OverlayFS将单个Linux主机上的两个目录进行分层,然后将它们表示为一个目录。这些目录就叫做layers,这个过程就被叫做unionmount。OverlayFS将靠下一层的目录叫做lowerdir,将靠上一层的叫做upperdir。然后经过处理后我们看到的那个目录叫做merged。

Linux各发行版实现的UnionFS各不相同,所以Docker在不同linux发行版中使用的UFS也不同。Docker支持几种不同的UFS实现,包括AUFS、Overlay、devicemapper、BTRFS和ZFS。哪一个被用看系统需要并且可以通过运行dockerinfo来检查,在“StorageDriver”下列出:

$dockerinfo|grep"Storage"StorageDriver:overlay2初代docker默认的存储驱动是AUFS,后来docker默认的存储驱动已经演进到了overlay2

每个容器都有它们自己的文件系统视图,Docker获取镜像所有的层,并使它们层叠在一起,以呈现为文件系统的一个视图。这个技术称为UnionMounting,Docker支持Linux上的几个UnionMount文件系统,主要是OverlayFS和AUFS。

Docker的文件系统是如何工作的?Docker镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(译者注:镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为UnionFileSystem(联合文件系统)。

Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

另外,不同Docker容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。

为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。

如果多个容器共享同一个基础镜像,基础镜像被修改,例如/etc/修改,是否会影响?答案是不会容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时,会先从镜像里要写的文件复制到容器自己的文件系统中(读写层)。如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作的,并不会修改镜像的源文件,这种方式提高磁盘利用率。若想持久化这些改动,可以通过dockercommit将容器保存成新的镜像

volume在容器创建时就会初始化,所以运行时就可以使用。在不同容器间共享和重用。对volume中数据的操作会马上生效。对volume中的数据操作不会影响到镜像本身。volume的生存周期独立于容器的生存周期,即使删除容器,volume依然存在,没有任何容器使用它,也不会被docker删除。

按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用dockerrm-v这个命令。

Docker在运行时分为Docker引擎(也就是服务端守护进程)和客户端工具。Docker的引擎提供了一组RESTAPI,被称为DockerRemoteAPI,而如docker命令这样的客户端工具,则是通过这组API与Docker引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种docker功能,但实际上,一切都是使用的远程调用形式在服务端(Docker引擎)完成。也因为这种C/S设计,让我们操作远程服务器的Docker引擎变得轻而易举。

dockerdaemon接受dockerapi的请求,并管理docker中定义的对象:镜像、容器、网络、数据卷等。dockerclient是大多数人与docker打交道的工具,比如当你输入dockerrun命令时,dockerclient将命令发到daemon执行。

安装Docker时,它会自动创建3个网络。可以使用dockernetworkls命令列出这些网络。这3个网络包含在Docker实现中。运行一个容器时,可以使用--net标志指定您希望在哪个网络上运行该容器。您仍然可以使用这3个网络。

bridge网络表示所有Docker安装中都存在的docker0网络。除非使用dockerrun--net=选项另行指定,否则Docker守护进程默认情况下会将容器连接到此网络。在主机上使用ifconfig命令,可以看到此网桥是主机的网络堆栈的一部分。none网络在一个特定于容器的网络堆栈上添加了一个容器。该容器缺少网络接口。host网络在主机网络堆栈上添加一个容器。您可以发现,容器中的网络配置与主机相同。

bridge即桥接网络,以桥接模式连接到宿主机,即宿主机和容器之间通过docker0虚拟网卡连到同一个局域网。bridge是默认的网络模式host宿主网络,即与宿主机共用网络,这种模式相当于没有网络隔离,好处是和宿主机处于同一网络,可随意访问,都不用-p做端口映射了。none则表示无网络,容器将无法联网

overlay跨主机网络。在早期的docker版本中,是不支持跨主机通信网络驱动的,也就是说明如果容器部署在不同的节点上面,只能通过暴露端口到宿主机上,再通过宿主机之间进行通信。docker1.9之后,随着dockerswarm集群的推广,docker也有了自家的跨主机通信网络驱动,名叫overlay,overlay网络模型是swarm集群容器间通信的载体,将服务加入到同一个网段上的Overlay网络上,服务与服务之间就能够通信。

安装Docker的时候,会在宿主机安装一个虚拟网卡docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。

$ifconfigdocker0:flags=4163mtu1500inet172.17.0.1netmask255.255.0.0broadcast172.17.255.255inet6fe80::42:88ff:fe56:8251prefixlen64scopeid0x20ether02:42:88:56:82:51txqueuelen0(Ethernet)RXpackets915966bytes2933746454(2.7GiB)RXerrors0dropped0overruns0frame0TXpackets875092bytes62233810(59.3MiB)TXerrors0dropped0overruns0carrier0collisions0Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。例如Linux下一般是172.17.0.1,并不固定。它还给出了MTU(接口允许接收的最大传输单元),通常是1500Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。

host网络和主机之间没有隔离,和主机共享一个networknamespace.

注意:使用host网络模式时,端口映射不起作用。dockerrun时的-p,--publish,-P,--publish-all参数会被忽略,并产生一条警告:WARNING:Publishedportsarediscardedwhenusinghostnetworkmode

host类型网络只能在Linux上使用,在Mac和Windows上不支持。ThehostnetworkingdriveronlyworksonLinuxhosts,andisnotsupportedonDockerDesktopforMac,DockerDesktopforWindows,orDockerEEforWindowsServer.

1、容器内访问宿主机使用docker.for.mac.host.internal或者host.docker.internal这两个特定域名可访问宿主机,这是docker容器内配置好的可解析到宿主机IP的DNS,可以直接当宿主机的IP使用。进入任意容器后,ping这两个域名都会解析到宿主机IP

2、宿主机访问容器通过-p端口映射。例如dockerrun-p8081:80-dnginx之后在主机上通过localhost:8081可直接访问容器内的80端口

docker-proxy是dockerd的子进程,用于端口映射。docker-proxy主要是用来做端口映射的。当我们使用dockerrun命令启动容器时,如果使用了-p参数,docker-proxy组件就会把容器内相应的端口映射到主机上来,底层是依赖于iptables实现的。

1、netstat-anp查看端口占用看到是docker-proxy进程,获取pid2、ps-ef|greppid查看进程命令,看到是监听宿主机8080端口转发到192.168.42.2容器的8080端口

root75958119310Aug2100:00:00/usr/local/bin/docker-proxy-prototcp-host-ip0.0.0.0-host-port8080-container-ip192.168.42.2-container-port80803、dockerps|grep8080端口,能看到是哪个容器在使用8080端口4、dockerinspectcontainer-id|grepIPAddress能看到使用8080端口的容器的ip就是192.168.42.2

chroot隔离文件系统namespace隔离进程访问cgroups隔离资源使用

docker并不是彻底的虚拟化,不同容器之间会共享内核。Linux虚拟机是完全的虚拟化,内核隔离。

LinuxCGroup全称LinuxControlGroup,是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)CGroup主要提供了如下功能:Resourcelimitation:限制资源使用,比如内存使用上限以及文件系统的缓存限制。Prioritization:优先级控制,比如:CPU利用和磁盘IO吞吐。Accounting:一些审计或一些统计,主要目的是为了计费。Control:挂起进程,恢复执行进程。

容器request/limit利用cgroupcpu公平调度器实现。

Docker只能安装在64位机器上。

前提条件:1安装DockerEngine-Community需要CentOS7版本及以上,老版本不支持。2需要开启centos-extrasyumrepo,默认是开启的。

1安装yum仓库管理工具yum-utils,以及device-mapper-persistent-data,lvm2

$sudoyuminstall-yyum-utils\device-mapper-persistent-data\lvm22安装dockerrepo

sudoyuminstalldocker-cedocker-ce-clicontainerd.io我安装的版本信息

sudosystemctlrestartdocker容器会全部停止,之后需要重启容器

停止docker服务systemctlstopdocker

查看当前版本rpm-qa|grepdocker

#rpm-qa|grepdockernvidia-container-runtime-2.0.0-1.docker17.06.2.x86_64docker-ce-17.06.2.ce-1.el7.centos.x86_64nvidia-docker2-2.0.3-1.docker17.06.2.ce.noarch删除当前版本yumremovedocker-ce-17.06.2.ce-1.el7.centos.x86_64

DockerDesktopforMac要求系统最低为2010年以后的Mac机型,准确说是带IntelMMU虚拟化的,macOS10.13及以上版本,最低4GB内存。如果不满足已上要求,可以使用DockerToolbox安装Docker来代替DockerDesktop,DockerToolbox使用OracleVirtualBox虚拟机而不是HyperKit虚拟机。

Homebrew的Cask已经支持DockerDesktopforMac,因此可以很方便的使用HomebrewCask来进行安装:brewinstall--caskdocker

查看docker版本docker--version

$docker--versionDockerversion19.03.5,build633a0ea启动一个nginx验证dockerrun-d-p80:80--namenginx--rmnginx

Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

定制镜像必须以一个镜像为基础,在其上进行定制。FROM指定基础镜像,因此一个Dockerfile中FROM是必备的指令,并且必须是第一条指令。Docker还存在一个特殊的镜像,名为scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。

VOLUME在镜像中创建挂载点VOLUME后的目录格式可以是纯文本的目录,空格分割的多个目录,或者json格式的字符串数组

VOLUME/var/logVOLUME/var/log/var/dbVOLUME["/data1","/data2"]相比于dockerrun时-v指定目录映射,VOLUME指令可实现通过此镜像创建的容器内都有一个预先创建好的目录,当然使用dockerrun-v也完全可以代替VOLUME指令。

ADD指令和COPY的格式和性质基本一致。但是在COPY基础上增加了一些功能。比如源路径可以是一个URL,这种情况下,Docker引擎会试图去下载这个链接的文件放到目标路径去。下载后的文件权限自动设置为600,如果这并不是想要的权限,那么还需要增加额外的一层RUN进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层RUN指令进行解压缩。所以不如直接使用RUN指令,然后使用wget或者curl工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用。

相比COPY,ADD其实就增加了2个特性:1、ADD指令可以让你使用URL作为src参数。当遇到URL时候,可以通过URL下载文件并且复制到dest2、ADD的另外一个特性是有能力自动解压文件。如果src参数是一个可识别的压缩格式(tar,gzip,bzip2,etc)的本地文件(所以实现不了同时下载并解压),就会被解压到指定容器文件系统的路径dest

WORKDIR<工作目录路径>使用WORKDIR指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR会帮你建立目录

RUN指令是用来执行命令行命令的,通常用于安装应用和软件包。Dockerfile中每一个指令都会建立一层,RUN也不例外。每一个RUN的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit这一层的修改,构成新的镜像。

例如

RUNapkadd--no-cachetzdata\&&ln-sf/usr/share/zoneinfo/Asia/Shanghai/etc/localtime\&&echo"Asia/shanghai">/etc/timezone\&&rm-rf/var/cache/apk/*/tmp/*/var/tmp/*$HOME/.cache##清除缓存RUNchmod+x/root/apps/start_jar.sh第一个安装时区的多条命令放在一个RUN中,保证构建在同一层镜像

CMD指令用于指定默认的容器主进程的启动命令的,此命令会在容器启动且dockerrun没有指定其他命令时运行,如果dockerrun后面指定其他命令则CMD会被忽略在运行时可以指定新的命令来替代镜像设置中的这个默认命令Dockerfile中可以有多个CMD指令,但只有最后一个生效

例如CMDecho"Helloworld"运行容器dockerrun-it[image]将输出Helloworld,但当后面加上一个命令,比如dockerrun-it[image]/bin/bash,CMD会被忽略掉,命令bash将被执行,会进入容器。

ENTRYPOINT用于设置容器启动时要执行的命令及其参数,当指定了ENTRYPOINT后,CMD的含义就发生了改变,不再是直接的运行其命令,而是将CMD的内容作为参数传给ENTRYPOINT指令,换句话说实际执行时,将变为:""与CMD不同的是,不管dockerrun…后是否运行有其他命令,ENTRYPOINT指令后的命令一定会被执行。Dockerfile中可以有多个ENTRYPOINT指令,也是只有最后一个生效

RUN命令会创建新的镜像层,通常用于安装应用和软件包。Dockerfile中常常包含多个RUN指令,每条RUN指令都会生成新的一层。CMD和ENTRYPOINT都可用于设置容器的启动命令,CMD会被dockerrun命令覆盖,而ENTRYPOINT不会,dockerrun命令中的参数都会成为ENTRYPOINT的参数。

ENTRYPOINT["/usr/bin/rethinkdb"]CMD["--help"]这个dockerfile里ENTRYPOINT后面还有个CMD的考虑是,如果dockerrun没有参数,CMD(–help)将成为ENTRYPOINT的默认参数,输出帮助信息,例如dockerrunrethinkdb时就会输出帮助信息。当dockerrun有参数时会代替CMD命令,例如dockerrun-itrethinkdbbash可以进入容器。

RUN/CMD/ENTRYPOINT命令的格式有两种:1、shell格式RUN/CMD/ENTRYPOINT<命令>就像直接在命令行中输入的命令一样。例如

指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合使用USER指定用户后,Dockerfile中后续的命令RUN、CMD、ENTRYPOINT都将使用该用户

也可以使用dockerrun-u指定用户

FROMiregistry.baidu-int.com/baidu-base/golang:1.19-alpine3.16ASbuilderCOPY--from=builder/app/bin//app/bin/二、dockerexport/import镜像导出再导入可压缩镜像

dockersystemdf查看docker磁盘占用汇总信息

dockersystemdfTYPETOTALACTIVESIZERECLAIMABLEImages43342117.4GB97.11GB(82%)Containers103892.145GB1.464GB(68%)LocalVolumes96116B58B(50%)BuildCache000B0BRECLAIMABLE是空闲镜像(没有任何容器使用的镜像)的大小,空闲镜像可以用命令dockerimageprune-a清理

dockersystemdf加-v参数显示详细的磁盘占用信息,能看到每个镜像、容器、卷的磁盘占用情况:

2、进入containers子目录,里面每个容器对应一个目录,目录名是容器ID,dockerps结果的第一列就是容器ID的前缀每个容器目录中有容器ID-json.log的日志文件,通常会比较大,可以直接>contain-id-json.log清理掉

新建或修改docker配置/etc/docker/daemon.json

34Me5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log48Me5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.148Me5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.248Me5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.348Me5e0fbde1e9b3ef24bef5228e2381936568f97d7da5b7214f3883f40bc32c809-json.log.4重启docker:

dockersystemprune会清理

dockerimageprune-a命令可批量清理悬空镜像

dockerimages看到的none镜像是悬空镜像(danglingimages),即无标签、且不被容器使用的镜像。

搜索DockerHub上的镜像

创建网络时,引擎默认为网络创建一个不重叠的子网。该子网不是现有网络的细分。它纯粹用于IP寻址目的。可以覆盖此默认值,并使用–subnet选项直接指定子网络值。在桥接网络上,只能创建单个子网。创建网络br0dockernetworkcreate--driver=bridge--subnet=192.168.0.0/16br0

dockerrun[OPTIONS]IMAGE[COMMAND][ARG...]以镜像IMAGE启动一个容器,如果IMAGE不存在,会从默认仓库DockerHub上下载此镜像,如果不指定tag默认是latest,启动容器后执行命令COMMAND

例1dockerrun-it--rmubuntu:18.04bash直接运行ubuntu镜像并进入启动的Ubuntu容器ubuntu:18.04:这是指用ubuntu:18.04镜像为基础来启动容器。bash:放在镜像名后的是命令,这里我们希望有个交互式Shell,因此用的是bash

例2dockerrun-itadoptopenjdk/openjdk8:centosbash会直接自动下载centos+jdk镜像,run镜像,并进入容器内

参数-d,--detach让Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下-e,--envlist启动容器时增加环境变量-p,--publish<宿主端口>:<容器端口>映射宿主端口和容器端口,-p标记可以多次使用来绑定多个端口。例如-p80:8080映射本机80端口到容器内的8080端口-P,--publish-all随机映射宿主机上一个49000~49900之间的端口到容器内部的网络端口--namestring指定启动的容器的名字--restartstring容器退出后的重启策略,默认是no,--restart=always可保持容器一直运行--rm容器退出后随之将其删除。默认情况下,为了启动失败时查错,退出的容器并不会立即删除,除非手动dockerrm。

-i,--interactive则让容器的标准输入保持打开,交互式操作-t,--tty让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上-it这两个参数一起使用,可进入容器执行命令。

--networknetwork,--netnetwork指定容器的网络模式,默认为bridgebridge即桥接网络,以桥接模式连接到宿主机,即宿主机和容器之间通过docker0虚拟网卡连到同一个局域网,bridge是默认的网络模式host宿主网络,即与宿主机共用网络,这种模式相当于没有网络隔离,好处是和宿主机处于同一网络,可随意访问,都不用-p做端口映射了。none则表示无网络,容器将无法联网container:c_name连接到容器c_name的网络network_name连接到预先创建好的网络network_name

-v,--volume[HOST-DIR:]CONTAINER-DIR[:OPTIONS]在本地(宿主机)和容器间映射目录或文件。注意此选项中HOST-DIR可以省略,但CONTAINER-DIR不能省略。如果只有一个目录,会被当做是CONTAINER-DIRHOST-DIR省略时,会自动在本机创建和容器中同名的目录。映射文件时文件名可以不相同。如果HOST-DIR和CONTAINER-DIR都存在,host上的文件/文件夹内容会覆盖container中的文件/文件夹内容。当映射文件时,宿主机文件必须存在,因为如果不存在会自动在宿主机创建,但此时创建的就是目录了。CONTAINER-DIR必须是绝对路径。HOST-DIR可以是绝对路径,或者volume卷名。HOST-DIR是绝对路径是,挂载此路径到容器。HOST-DIR是卷名时,挂载此卷(没有会自动创建volume)到容器。

挂载目录-vA:B时

-v可以出现多次,挂载多个不同的目录。

容器销毁后,启动容器时创建的宿主机目录不会销毁,容器运行过程中对目录的操作也都会保留在宿主机。

--mount挂载本地卷、目录、文件到容器中。由多个键值对组成,由逗号分隔,每一个由key=value元祖组成。键值对没有顺序。type,可以是bind,volume,tmpfs。source,主机上的文件或目录的路径。可能用src,source指定。destination,容器中的文件或目录的路径。可能用destination,dst,target指定。使用-v和–volume绑定主机不存在的文件或目录,将会自动创建。始终创建的是一个目录。使用–mount绑定主机上不存在的文件或目录,则不会自动创建,会产生一个错误。

-u,--user指定容器用户,格式[:]使用dockerrun启动容器应用的时候,默认使用的是root用户,并且这个root用户和宿主机中的root是同一个用户,所以容器应用进程具有很高的权限

例如dockerrun-u1000:1000-itubuntubashdockerrun-ucentos-itcentos:7bash

大约在0.6版,privileged被引入docker。使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。

M1Mac上运行amd64/x86_64架构镜像,可以指定--platformlinux/amd64参数

dockerrun-d--rm\--platformlinux/amd64\-p8001:8001\--nameblog\-v/var/log/spring:/var/log/spring\-e"SPRING_PROFILES_ACTIVE=local"\blog如果镜像本身是amd64/x86_64架构的,不需要指定,但dockerrun会报警告:WARNING:Therequestedimage’splatform(linux/amd64)doesnotmatchthedetectedhostplatform(linux/arm64/v8)andnospecificplatformwasrequested

1、dockerps-a能显示启动失败的容器,然后dockerlogs-f看启动日志有无报错2、dockerinspect看容器信息

3、如果dockerps-a也看不到容器,可以去掉-d后台运行参数,前台运行,而是-it把容器日志打印到前台,看有什么报错。

其中Architecture是镜像的架构

当用户获取一个镜像时,Docker引擎会首先查找该镜像是否有manifest列表,如果有的话Docker引擎会按照Docker运行环境(系统及架构)查找出对应镜像(例如golang:alpine)。如果没有的话会直接获取镜像(例如上例中我们构建的username/test)。

dockerpull[选项][DockerRegistry地址[:端口号]/]仓库名[:标签]具体的选项可以通过dockerpull–help命令看到Docker镜像仓库地址:地址的格式一般是<域名/IP>[:端口号]。默认地址是DockerHub。仓库名:如之前所说,这里的仓库名是两段式名称,即<用户名>/<软件名>。对于DockerHub,如果不给出用户名,则默认为library,也就是官方镜像。

例如dockerpullubuntu:18.04上面的命令中没有给出Docker镜像仓库地址,因此将会从DockerHub获取镜像。而镜像名称是ubuntu:18.04,因此将会获取官方镜像library/ubuntu仓库中标签为18.04的镜像。

有的镜像同一tag提供多架构的,可通过–platform参数指定架构

dockerpulladoptopenjdk/openjdk8:centos–platformamd64dockerpullcentos:7–platformlinux/amd64

一般默认情况下docker镜像的存放位置为/var/lib/docker(可通过dockerinfo命令查看DockerRootDir配置项),而此目录一般不会分配很大空间,docker上跑的东西太多就会发现此目录满了。

注意:Mac虽然dockerinfo看到的DockerRootDir也是/var/lib/docker,但其实镜像并不在这里,而是在$HOME/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw这个单独的文件中,并且无法修改。

解决方法:

OPTIONS=--graph="/root/data/docker"--selinux-enabled-Hfd://2、如果docker是1.12或以上的版本,可以修改(或新建)/etc/docker/daemon.json文件。修改后会立即生效,不需重启docker服务。改为

ExecStart=/usr/bin/dockerd-g/data/docker/-Hfd://然后systemctldaemon-reload重载unit配置文件

docker镜像所在磁盘空间不足时pullimage会报这个错误。

dockerimagels列出镜像,等价于dockerimages

dockerimagelsubuntu根据仓库名列出镜像dockerimagelsubuntu:18.04指定仓库名和标签列出镜像dockerimagels-q只列出镜像ID,经常用做其他命令的输入参数

dockerimagerm[选项]<镜像1>[<镜像2>...]等价于dockerrmi

dockerimagermcentos用镜像名,也就是仓库名:标签,来删除镜像dockerimagerm$(dockerimagels-qredis)删除所有仓库名为redis的镜像dockerimagerm$(dockerimagels-q-fbefore=mongo:3.2)删除所有在mongo:3.2之前的镜像

dockerbuild[选项]<上下文路径/URL/->-t,--tag指定image文件的名字,后面还可以用冒号指定标签,例如name:tag。如果不指定,默认的标签就是latest-f,--file指定Dockerfile文件名称,默认是PATH/Dockerfile

dockerbuild-tmyapp.在当前目录使用Dockerfile构建myapp镜像dockerbuild-tmyapp-fpath-to-Dockerfile.在当前目录使用path-to-Dockerfile构建myapp镜像

构建amd64架构的镜像

如果Dockerfile中指定了特定架构的基础镜像,例如FROMubuntu:amd64,则构建的镜像继承了基础镜像的架构,因此也是amd64架构的

docker构建命令dockerbuild[选项]<上下文路径/URL/->最后需要制定上下文目录当构建的时候,用户会指定构建镜像上下文的路径,dockerbuild命令得知这个路径后,会将路径下的所有内容打包,然后上传给Docker引擎。这样Docker引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

如果在Dockerfile中这么写:COPY./package.json/app/这并不是要复制执行dockerbuild命令所在的目录下的package.json,也不是复制Dockerfile所在目录下的package.json,而是复制上下文(context)目录下的package.json。

一般来说,应该会将Dockerfile置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给Docker引擎,那么可以用.gitignore一样的语法写一个.dockerignore,该文件是用于剔除不需要作为上下文传递给Docker引擎的。

实际上Dockerfile的文件名并不要求必须为Dockerfile,而且并不要求必须位于上下文目录中,比如可以用-f../Dockerfile.php参数指定某个文件作为Dockerfile。

.dockerignore用于剔除不需要作为上下文传递给Docker引擎的文件

--no-trunc不截断输出结果,不加这个选项的话CREATEDBY中显示不全

dockercontainerstop等于dockerstopdockerstop[OPTIONS]CONTAINER[CONTAINER...]

dockerrm等于dockercontainerrmdockerrm[OPTIONS]CONTAINER[CONTAINER...]如果要删除一个运行中的容器,可以添加-f参数。Docker会发送SIGKILL信号给容器。

dockerexec等于dockercontainerexecdockerexec[OPTIONS]CONTAINERCOMMAND[ARG...]-it这两个参数一起使用,可进入容器执行命令。常用格式dockerexec-it容器IDbashdockerexec-it容器IDsh

先查看当前运行的容器

原因:原因是该容器并没有bash解决:改用shdockerexec-it33e828194205sh

当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而Docker提供了一个dockercommit命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。

dockercommit[选项]<容器ID或容器名>[<仓库名>[:<标签>]]

-a,--authorstring指定修改的作者-m,--messagestring记录本次修改的内容

$dockercommit\-a"TaoWang"\-m"修改了默认网页"\webserver\nginx:v2其中-a指定修改的作者,而-m则是记录本次修改的内容,这点和git版本控制相似,不过这里这些信息可以省略留空。

保存镜像到tar文件,默认输出到stdout,默认包含所有的layer,所有的tags,当然也可以指定tags-o,--outputdockersave默认是输出到stdout,通过-o参数可指定保存的档案文件名

dockersavebusybox>busybox.tar保存镜像busybox的所有版本到busybox.tar文件dockersave-omyimage.tarmyimage:tag1保存镜像myimage的tag1版本到myimage.tar文件

方法一、利用gzip/gunzip压缩解压导出镜像并压缩为gzipdockersavemyimage:latest|gzip>myimage_latest.tar.gz导出镜像并压缩

倒入镜像压缩包gunzip-cmyimage_tag.tar.gz|dockerload

方法二、或者使用tar命令压缩和解压

dockersavemyimage:tag>myap.tartar-zcvfmyap.tar.gzmyap.tar解压导入镜像

tar-xzvfmyap.tar.gzdockerload

1、在可以联网的机子上执行dockerpull命令下载镜像,如:sudodockerpullfreewil/bitcoin-testnet-box,命令使用参考Dockerpull命令2、然后运行dockersave命令将镜像保存为tar归档文件,如:dockersave-obitcoin-testnet-box.tarfreewil/bitcoin-testnet-box,命令使用参考Dockersave命令3、将保存的bitcoin-testnet-box.tar归档文件拷贝进内网机器4、内网机器上执行dockload命令加载保存的tar归档文件,如:dockerload-ibitcoin-testnet-box.tar

从tar文件或标准输入stdin导入镜像,会重建镜像和所有的tag.这里的tar文件是用dockersave命令导出的镜像。--input,-i:指定导入的文件,代替STDIN--quiet,-q:精简输出信息。

dockerload

dockercp等于dockercontainercpdockercp[OPTIONS]CONTAINER:SRC_PATHDEST_PATH|-dockercp[OPTIONS]SRC_PATH|-CONTAINER:DEST_PATH

示例1、将容器中的文件/root/123.mp4拷贝到宿主机的/root/mp4/目录中,其中335d957237c9是容器id

dockercp335d957237c9:/root/123.mp4/root/mp4/2、将容器中的/root/images目录拷贝到宿主机的/root/data/目录中,其中335d957237c9是容器id

dockercp335d957237c9:/root/images/root/data/3、将宿主机当前目录中的xx.mp4文件拷贝到容器的/root/data/目录中,其中video-processor是容器名

dockerlogs[OPTIONS]CONTAINER如果容器无法启动,先dockerps-a找到启动失败的容器id,然后dockerlogs容器id查看失败日志注意为了保留启动失败的容器,不能加--rm否则失败后容器文件就被删除了。dockerlogs-f容器id以滚动方式查看容器日志

dockerinspect[OPTIONS]NAME|ID[NAME|ID...]

从Docker20.10.0版本开始,将docker-compose集成到了docker命令中,docker命令内开始包含了compose子命令但这仍然是一个实验性的功能,并不是所有的Docker安装都包含此功能,需要修改~/.docker/config.json"experimental":"enabled"来启用实验性功能,然后重启docker

从Docker20.10.0版本开始,将docker-compose集成到了docker命令中,docker命令内开始包含了compose子命令compose用于定义和运行由多个docker镜像组成的service,可通过配置文件配置service由哪些镜像组成,然后通过一个命令一次性将这些docker镜像启动。

1、下载二进制可执行文件,命名为docker-compose

3、查看版本,有输出就是安装成功

compose文件包含了4个顶级键:version:指定文件规范版本services:指定要操作的容器networks:指定共用的网络配置volumes:指定共用的存储配置

可以使用docker-composeconfig验证和查看待操作的Compose文件

compose配置文件格式版本Docker版本3.819.03.0+3.718.06.0+3.618.02.0+3.517.12.0+3.417.09.0+3.317.06.0+3.217.04.0+3.11.13.1+3.01.13.0+2.417.12.0+2.317.06.0+2.21.13.0+2.11.12.0+2.01.10.0+1.01.9.1.+

解决容器的依赖、启动先后的问题。以下例子中会先启动redisdb再启动web

如果你使用默认配置文件名称,不需要显式指定-fdocker-compose.yml如若需指定配置文件,必须在docker-compose后面指定,不能在up等子命令后面指定,否则无效;

-d,--detach后台启动默认情况,docker-composeup启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。当通过Ctrl-C停止命令时,所有容器将会停止。如果使用docker-composeup-d,将会在后台启动并运行所有的容器。

--no-recreate默认情况,如果服务容器已经存在,docker-composeup将会尝试停止容器,然后重新创建(保持使用volumes-from挂载的卷),以保证新启动的服务匹配docker-compose.yml文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用docker-composeup--no-recreate这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果需要的话,这样将会启动已经停止的容器。

指定service如果用户只想重新部署某个服务,可以使用docker-composeup--no-deps-d来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。

链接的服务都将会启动,除非他们已经运行。

start启动一个已经存在的服务容器。

停止一个已经运行的容器,但不删除它。通过docker-composestart可以再次启动这些容器。

查看容器,在docker-compose.yml所在目录中执行docker-composeps只查看此compose.yml描述的容器状态

#docker-composepsNameCommandStatePorts-------------------------------------------------------------------------------------------------zookeeper_1/docker-entrypoint.shzkSe...Up0.0.0.0:2181->2181/tcp,2888/tcp,3888/tcpzookeeper_2/docker-entrypoint.shzkSe...Up0.0.0.0:2182->2181/tcp,2888/tcp,3888/tcpzookeeper_3/docker-entrypoint.shzkSe...Up0.0.0.0:2183->2181/tcp,2888/tcp,3888/tcp当然也可以直接dockerps查看所有容器的状态

默认情况下,应用程序的网络名称基于Compose的工程名称,而项目名称基于docker-compose.yml所在目录的名称。如需修改工程名称,可使用–project-name标识或COMPOSE_PORJECT_NAME环境变量。

举个例子,假如一个应用程序在名为myapp的目录中,并且docker-compose.yml如下所示:

version:"3"services:web:build:.ports:-"8000:8000"db:image:postgresports:-"8001:5432"当我们运行docker-composeup时,将会执行以下几步:

创建一个名为myapp_default的网络;使用web服务的配置创建容器,它以“web”这个名称加入网络myapp_default;使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default。

等于docker命令的--network参数

1、注册DockerHub账号

#查看本地镜像$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEmasikkk/centos7-openjdk21202401235996f993958f7weeksago720MBmasikkk/centos7-openjdk21-tesseract2024012315a6611140d740hoursago1.07GB打镜像tag时需要注意名称中必须包含DockerHub账号,我的账号是masikkk,则镜像必须是masikkk/开头,否则推送到DockerHub时报错:

library/registry是官方提供的工具,可以用于构建私有的镜像仓库。也就是这个私人仓库程序本身就是一个镜像。使用官方的registry镜像来启动私有仓库。默认情况下,仓库会被创建在容器的/var/lib/registry目录下。通过-v将本地目录/home/centos/docker/registry映射到容器的/var/lib/registry目录,这样上传到容器的镜像就保存到本地了。

crane是一个与远程镜像和仓库交互的工具,由Googlecontainerregistry开发

将本地镜像内容推送到远程仓库crane–insecurepushmyapp-1.2.1.tarlocalhost:5000/myapp:1.2.1

BusyBox是一个集成了一百多个最常用Linux命令和工具(如cat、echo、grep、mount、telnet等)的精简工具箱,它只需要几MB的大小,很方便进行各种快速验证。

dockerbuild-fcentos7-openjdk21-nodejs16-hexo7.Dockerfile-tmasikkk/centos7-openjdk21-node16-hexo7:20240317.

dockerrun-d-it--rm\-v~/.ssh:/home/centos/.ssh\masikkk/centos7-openjdk21-node16-hexo7:20240317bash后台启动容器,然后dockerexec进入容器

安装gitsudoyuminstall-ygit

安装nodejs17

只有amd64架构的

AdoptOpenJDK已被官方废弃,最高只到jdk16注意此镜像有多种架构,M1Mac上默认会拉取arm64架构的版本,如果想要使用amd64/x86_64架构版本,需要通过--platformamd64参数指定

dockerpulladoptopenjdk/openjdk8:centos–platformamd64dockerpulladoptopenjdk/openjdk8:centos-slim–platformamd64

REPOSITORYTAGIMAGEIDCREATEDSIZEadoptopenjdk/openjdk8centos-slimf7719a74b21017hoursago471MBadoptopenjdk/openjdk8centosa72f04e4db6d17hoursago579MB

1、创建centos7-openjdk8.Dockerfile

FROMcentos:7MAINTAINERmasikkk.comRUNyumupdate-y&&\yuminstall-ywget&&\yuminstall-yjava-1.8.0-openjdkjava-1.8.0-openjdk-devel&&\yumcleanall#Setenvironmentvariables.ENVHOME/root#Defineworkingdirectory.WORKDIR/root#Definedefaultcommand.CMD["java","-version"]2、构建镜像进入centos7-openjdk8.Dockerfile文件所在目录dockerbuild-fcentos7-openjdk8.Dockerfile-tmasikkk/centos7-openjdk8:20240123.结果

$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEmasikkk/centos7-openjdk820240123a44b575730c856secondsago602MB3、运行镜像,由于Dockerfile里的CMD命令就是java-version,执行dockerrun可直接看到java版本

$dockerrunmasikkk/centos7-openjdk8:20240123openjdkversion"1.8.0_392"OpenJDKRuntimeEnvironment(build1.8.0_392-b08)OpenJDK64-BitServerVM(build25.392-b08,mixedmode)也可以执行dockerrun-it--rmcentos7-openjdk8:20240123bash进入镜像看看java版本

4、推送到DockerHub

注意:下面docker镜像的构建是在linux上执行的,如果在M1Mac上打镜像但最后在Linux上跑,需要注意M1Mac上默认会拉下来arm64架构的镜像,而Linux上需要amd64架构的镜像。

1、创建centos7-openjdk21.Dockerfile

dockerbuild-fcentos7-openjdk21.Dockerfile-tmasikkk/centos7-openjdk21:20240123.结果:

$dockerimagesREPOSITORYTAGIMAGEIDCREATEDmasikkk/centos7-openjdk21202401235996f993958f7weeksago720MB3、执行dockerrunmasikkk/centos7-openjdk21:20240123验证,由于Dockerfile里的CMD命令就是java-version,dockerrun可直接看到java版本

$dockerrunmasikkk/centos7-openjdk21:20240123openjdkversion"21.0.1"2023-10-17OpenJDKRuntimeEnvironment(build21.0.1+12-29)OpenJDK64-BitServerVM(build21.0.1+12-29,mixedmode,sharing)也可以dockerrun-it--rmmasikkk/centos7-openjdk21:20240123bash进入容器验证或者dockerrun-d-it--rmmasikkk/centos7-openjdk21:20240123bash后台启动容器,然后dockerexec进入容器。

1、创建centos7-openjdk21-tesseract.Dockerfile

dockerbuild-fcentos7-openjdk21-tesseract.Dockerfile-tmasikkk/centos7-openjdk21-tesseract:20240123.结果:

$dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEmasikkk/centos7-openjdk21-tesseract2024012315a6611140d740hoursago1.07GB3、执行dockerrunmasikkk/centos7-openjdk21-tesseract:20240123由于CMD默认命令是tesseract-v,可直接看到tesseract版本号:

$dockerrunmasikkk/centos7-openjdk21-tesseract:20240123tesseract4.1.3leptonica-1.76.0libjpeg6b(libjpeg-turbo1.2.90):libpng1.5.13:libtiff4.0.3:zlib1.2.7:libwebp0.3.0FoundAVX2FoundAVXFoundFMAFoundSSE也可以dockerrun-it--rmmasikkk/centos7-openjdk21-tesseract:20240123bash进入容器验证。

1、在项目根目录下添加Dockerfile文件:

2、先用maven把springboot项目打包为可运行的jar包mvnpackage

3、构建SpringBootDocker镜像在Dockerfile所在的项目根目录下构建镜像dockerbuild-tblog-server.注意一定要在Dockerfile所在的目录,最后那个.指定了当前目录是构建上下文。

dockerrun-d--rm\--networkhost\--nameblog-server\-v/var/log/spring:/var/log/spring\-e"SPRING_PROFILES_ACTIVE=local"\blog-server解释下

启动后进入容器dockerexec-itblog-serversh查看系统版本

dockerrun-d--rm\-p8001:8001\--nameblog\-v/var/log/spring:/var/log/spring\-e"SPRING_PROFILES_ACTIVE=local"\blogM1Mac上运行amd64/x86_64架构镜像

如果不带标签的话,默认拉取的是latest版本镜像,也就是1.17.9,mainline,1,1.17,latest,这个版本用的是debian:buster-slimlinux,不是很习惯,好多基本命令没有。所以加上alpine标签拉取1.17.9-alpine,mainline-alpine,1-alpine,1.17-alpine,alpine版本镜像

拉取官方nginxalpine版本镜像的最新版dockerpullnginx:alpine

进容器中查看系统版本查看/etc/os-release文件

#nginx-vnginxversion:nginx/1.17.9配置目录/etc/nginx/nginx.conf日志目录/var/log/nginx/error.log/var/log/nginx/access.log

还使用原始的nginx:alpine官方镜像,只不过在启动命令中加入自己的配置,很方便

aws上的nginx

dockerrun-d--rm\--networkhost\--namenginx\-eTZ="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解释:

在nginx-centos.conf文件所在的目录中新建Dockerfile文件

FROMnginx:alpineCOPYnginx-centos.conf/etc/nginx/nginx.confRUNecho"Asia/shanghai">/etc/timezone\&&ln-sf/usr/share/zoneinfo/Asia/Shanghai/etc/localtime解释:

在Dockerfile所在目录内执行dockerbuild-tnginx-masikkk.构建自己的nginx镜像,名为nginx-masikkk,以当前路径为上下文路径一定要注意上下文路径是当前所在文件夹,所以COPY指令才可以直接拷贝当前文件夹中的nginx-centos.conf文件

$dockerbuild-tnginx-masikkk.SendingbuildcontexttoDockerdaemon15.87kBStep1/3:FROMnginxlatest:Pullingfromlibrary/nginxDigest:sha256:50cf965a6e08ec5784009d0fccb380fc479826b6e0e65684d9879170a9df8566Status:Downloadednewerimagefornginx:latest--->231d40e811cdStep2/3:COPYnginx-centos.conf/etc/nginx/nginx.conf--->e45c37eea53fStep3/3:RUNecho"Asia/shanghai">/etc/timezone&&cp/usr/share/zoneinfo/Asia/Shanghai/etc/localtime--->Runninginf8cc0a26834aRemovingintermediatecontainerf8cc0a26834a--->20ad396f30eaSuccessfullybuilt20ad396f30eaSuccessfullytaggednginx-masikkk:latest查看构建好的镜像

$dockerimagelsREPOSITORYTAGIMAGEIDCREATEDSIZEnginx-masikkklatest20ad396f30ea4secondsago126MBnginxlatest231d40e811cd4weeksago126MB启动自己的nginx容器

dockerrun-d--rm\--networkhost\--namenginx\-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这样启动命令可以少两个参数。

docker版nginx默认以用户nginx启动,一开始我使用了自己当前的用户,一直无法启动报错2019/12/2303:49:40[emerg]1#1:getpwnam(“centos”)failedin/etc/nginx/nginx.conf:2nginx:[emerg]getpwnam(“centos”)failedin/etc/nginx/nginx.conf:2在nginx.conf中改为usernginxnginx;后好了

docker太方便了,准备好配置文件后直接启动就行,自动从dockerhub拉取最新官方镜像我的启动命令如下:

dockerrun-d--rm\--networkhost\--nameprometheus\-v/home/centos/git/masikkk/prometheus.yml:/etc/prometheus/prometheus.yml\prom/prometheus解释下:-d后台运行--rm停止容器后删掉容器文件--networkhost与宿主机完全共享网络,默认是bridge桥接,无法在nginx中通过localhost转发请求--namegrafana指定启动的容器名,方便按名称stop等操作-v映射配置文件,具体说是宿主机配置文件覆盖容器中的配置文件,我的配置文件在git仓库中,方便保存,也可以记录修改历史。

第一次执行时直接从dockerhub拉取最新版本grafana

dockerrun-d--rm\--networkhost\--namegrafana\grafana/grafana解释下:-d后台运行--rm停止容器后删掉容器文件--networkhost与宿主机完全共享网络,默认是bridge桥接,无法在nginx中通过localhost转发请求--namegrafana指定启动的容器名,方便按名称stop等操作

方法一,bridge网络模式的容器使用宿主机在docker0网卡上的ip访问宿主机。安装Docker的时候,会在宿主机安装一个虚拟网卡docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。在宿主机上ifconfig查看docker0网卡的ip地址,Linux下一般是172.17.0.1,macOS下一般是192.168.65.1,并不固定。在容器中使用宿主机ip访问的问题是,配置写死ip非常不灵活,和dockeranywheredeploy的原则相悖。

方法二,使用host宿主机网络模式启动容器Docker容器运行的时候有host、bridge、none三种网络可供配置。默认是bridge,即桥接网络,以桥接模式连接到宿主机;host是宿主网络,即与宿主机共用网络;none则表示无网络,容器将无法联网。

当容器使用host网络时,容器与宿主共用网络,这样就能在容器中访问宿主机网络,那么容器的localhost就是宿主机的localhost。启动容器时加参数--networkhost表示已宿主机网络模式启动容器。此时不需要-p80:80做端口映射了,因为本身与宿主机共用了网络,容器中暴露端口等同于宿主机暴露端口。这种模式的问题是破坏了容器之间的隔离性,好处是网络访问很方便。

容器中的nginx日志文件都重定向到了重启的标准输出和标准错误输出,所以直接到容器中看access.log是没有内容的。有如下两个方法看日志:1、可以在容器外通过dockerlogs-fnginx-name查看日志/var/log/nginx/access.log->/dev/stdout/var/log/nginx/error.log->/dev/stderr

2、启动容器时-v/var/log/nginx:/var/log/nginx将容器内日志目录映射到本机,之后直接在本机即可看日志。

在alpine镜像中使用诸如jstack,jinfo工具,有如下报错:1:UnabletogetpidofLinuxThreadsmanagerthread

原因是pid为1,发现PID为1的时候,工具不可用。

解决:1、Dockerfile里使用如下命令启动:CMD["/bin/sh","-c","javaAPP","&&1"]2、或者使用--init参数来启动docker

docker启动springbootjava服务报错:

[0.007s][warning][os,thread]Failedtostartthread"GCThread#0"-pthread_createfailed(EPERM)forattributes:stacksize:1024k,guardsize:4k,detached.##ThereisinsufficientmemoryfortheJavaRuntimeEnvironmenttocontinue.#CannotcreateworkerGCthread.Outofsystemresources.#Anerrorreportfilewithmoreinformationissavedas:#//hs_err_pid7.log解决:docker启动命令添加参数--privileged特权模式

某些需要绘制图表的java应用在docker中可能遇到这个问题,比如需要创建excel表格的,原因是缺少字体配置。

可以进入容器修改时区,不推荐dockerexec-itbashecho"Asia/Shanghai">/etc/timezone

启动容器时用环境变量TZ指定时区dockerrun-eTZ="Asia/Shanghai"-d-p80:80--namenginxnginx

启动容器时-v绑定主机时区文件利用volume可以在启动一个container时指定使用主机的时区文件,就可以把container的时区与主机同步dockerrun-v/etc/localtime:/etc/localtime

如果是打包自己的镜像,可以在Dockerfile中增加

RUNecho"Asia/shanghai">/etc/timezone\&&ln-sf/usr/share/zoneinfo/Asia/Shanghai/etc/localtime前提是容器的linux中本身就有/usr/share/zoneinfo/Asia/Shanghai时区文件

alpine中默认也是UTC时区,需要改为东八区,但alpine中默认又没有/usr/share/zoneinfo/Asia/Shanghai时区文件,只能先安装时区文件tzdata,再链接到/etc/localtime

因为通过-v映射了一个不在共享配置中的文件夹

Mac系统中想要和容器共享文件夹的话,需要先配置默认已共享了/Users/,/Volumes/,/private/,and/tmp可在Preferences->Filesharing中增加共享目录

mac中没有docker0虚拟网卡受限于DockerDesktopforMac底层的网络实现,Mac上的docker没有docker0网卡。

从容器中访问mac网络的方法通过调试用DNShost.docker.internal

从mac上访问容器网络的方法:使用-p80:80暴露端口,--networkhost不起作用

为了在M1Mac上模拟运行amd64/x86_64架构的Linux环境,需要构建和运行amd64/x86_64架构镜像。

1、M1Mac上构建amd64/x86_64架构镜像dockerbuild-fdevops/blog.Dockerfile–platform=amd64-tblog.

2、M1Mac上运行amd64/x86_64架构镜像,可以指定--platformlinux/amd64参数

THE END
1.javalibrary图书馆为什么登录不进去三、账号问题 还有一种可能是您的账号问题。请确认您的账号是否有效,以及是否有访问图书馆的权限。如果您忘记了账号或者密码,可以尝试找回账号或者重置密码。四、软件或浏览器问题 如果以上都不是问题所在,那么可能是您的浏览器或者Java软件版本过旧,不支持访问Javalibrary图书馆。请尝试更新您的浏览器或https://zhidao.baidu.com/question/1779003936112384220.html
2.zliabary怎么登不上去了zliabary怎么登不上去了向钱看齐 精选回答 品牌型号:华为P50系统:HarmonyOS3软件版本:zliabary4.00 如果你无法登录Z-Library,可能有以下几种原因: 1、登录信息错误:请检查你输入的用户名和密码是否正确,特别是大小写是否一致。如果你忘记了密码,可以尝试通过“忘记密码”功能重置密码。 2、网络问题:请确保你的https://edu.iask.sina.com.cn/jy/hMT2HLv2Gz.html
3.library.skshu.com/yyys98714181.htm免费看黄色不要钱放心吧 成人无码一级视频 kTV三陪裸体公主视频 插深一点用力好多水视频 美女裸体无遮挡网站观看 美国国产Av 操逼视频地址 女人奶水freeXX× 国产寡妇树林野战在线播放 我和亲妺妺乱的性VR视频 www.午夜插进去 国产女人和黑人学英语的黄色网站 久久成人午夜福利亚洲一区亚洲Av无码专区 jk扒开http://library.skshu.com/yyys98714181.htm
4.解决ZLibrary登录/注册不了的问题zliabary注册验证不了转载链接:解决 ZLibrary 登录/注册不了的问题 - 知乎 很多小伙伴反馈说 Z-Library能打开,但是不能登录。这实际上是由于官方登录入口受限导致的。话虽如此,我们仍然可以通过某些方法绕过这个限制。 >虽然我们注册时用的时密码和邮箱,但经过分析,我们登录时实际上用的是 remix_userid 和 remix_userkey 这两个东西https://blog.csdn.net/m0_49448331/article/details/126546230
5.登进去z登进去z-library的感觉就像是进了Costco[awsl] https://weibo.com/6786598203/LEnEgzRPN
6.BlackNoMoreModernLibrary英文原版小说黑色不再兰登书屋当当华研外语旗舰店在线销售正版《Black No More Modern Library 英文原版小说 黑色不再 兰登书屋现代图书馆 George S. Schuyler 英文版 进口英语原版书籍》。最新《Black No More Modern Library 英文原版小说 黑色不再 兰登书屋现代图书馆 George S. Schuyler 英文版 进口http://product.dangdang.com/11453072510.html?point=comment_point
7.图文解决育碧uplay连不上服务器登录不上去办法这些游戏不仅画面精美、玩法独特,更重要的是,它们都有着扣人心弦的剧情,让人一玩就停不下来。不过,有时候在享受游戏的过程中,也会遇到一些小插曲,比如育碧uplay突然连不上服务器,登录不上去,这可真是急死个人了。别急,下面几个方法或许能帮你解决问题。https://www.bilibili.com/read/cv38059375/
8.登录?站点进入网站专属NBA杯1/4决赛,勇士在客场以90-91不敌火箭,无缘半决赛。这场比赛勇士打得确实无奈,本来都保持领先了,无奈最后时刻连续出现懵逼操作,最终造成的结果就是他们无缘最终的胜利。赛后他们还遭遇三个坏消息。 一个是库里,他在最后提前出手这是大忌。当然库里看到空位了,想当英雄。无奈的是,末节他的状态非常糟糕,一直http://m.mervxis.cn/PAZ/moa/RhP.html
9.Word账号登不上怎么办啊Word账号登不上怎么办啊浏览量:314ipad上Word登不上怎么办啊 溜云库qq登不上怎么办 溜云库登不上qq怎么办 Word安装不上怎么办啊 虎课网账号登不上 手机PS软件登不上怎么办 电脑上没Word怎么办啊 Word电脑上没有了怎么办啊 为您找到1500条“Word账号登不上怎么办啊”相关问题https://www.3d66.com/answers_relation/relation_649970_10.html
10.jsjy.smt66.com/mokpage12671.html刚开始演唐僧的时候,聂远刚演完《三国演义》里的赵云,还没走出舞刀弄枪的氛围,所以他戏称自己是“见了妖怪就满脸杀气,总想干孙悟空的活儿。”后来是听取了导演的建议,每天吃素、打坐、念经,使整个人沉下来,开始从另外一个角度去看唐僧,慢慢理解了唐僧心中的“众生平等”,所以才会不原谅孙悟空总是去打杀妖精,而http://jsjy.smt66.com/mokpage12671.html
11.Javlibrary被屏蔽登录不了Javlibrary怎么破.docJavlibrary 被屏蔽_ 登录不了 Javlibrary 怎么破在这里小编教大家登陆方法! 工具/原料首先你要有小语 VPN 账号一个电脑一台方法/步骤 1 用已经注册号的账号登陆 2 之后我们选择一个节点。任意。我们来选个日本线路试试链接之后我们注意下 IP地址是不是显示在日本, 现在就可https://www.taodocs.com/p-39938610.html
12.磁力搜索哪个最好用?(「整理收集」那些神器级别的BT磁力搜索网站2.磁力搜索-手撕包菜(网站暂时打不开) 中文站点,简洁好用。 http://bt.shousibaocai.com/ 3.Bt Kitty 中文站点,特色是文件标签,可以提供类似的资源。 http://btkitty.org 4.BT图书馆(BTLibrary.com) 不支持BT展开搜索。 http://btlibrary.com https://www.bb1314.com/news/39239.html
13.初三上学期英语词组= a book from the library 一本图书馆的书 5. used to do sth. (过去)经常做某事 6. usedn’t to do sth (过去)经常不做某事 7. didn’t use to do sth. (过去)经常不做某事 8. Did sb. use to do sth. ? (过去)经常做某事吗? http://d.zww.cn/chuzhong/yingyu/nianji3/1/3998.htm
14.克莉絲蒂推理全集另以女性直覺、打破砂鍋、人性關懷見長的珍.瑪波,同為推理之后一手捧紅的超級巨星,舉世聞名、歷久不衰。白羅也是推理史上唯一登上《紐約時報》訃聞的古典第一偵探,超凡魅力可見一斑!在克莉絲蒂小說中,珍瑪波共出場十四部長篇推理小說,白羅則出場三十三部長篇小說、六十五篇短篇小說。https://www.ylib.com/hotsale/2020-New-YLib/PTO/3J-R@Agatha-Christie-Novels-complete-works/index.asp
15.英文版网站无法正常登录北京大学图书馆(PKULibrary)版不如让所有用户默认看中文的,让想看英文的人点“English”进去看。lib-blocked.png(29.6KB)https://bbs.pku.edu.cn/v2/post-read-single.php?bid=25&postid=17064784
16.Zlibrary2024不用登录下载Zlibrary2024安卓版下载v1.065应用标签:生活Zlibrary 扫描二维码下载 应用介绍 Zlibrary2024是一款非常好用的小说阅读软件,可以在这里查询到各种各样的小说内容,而且可以关注自己比较喜欢的各种书籍。都是非常高质量的,可以发现更多有趣的图书,按照不同的目录来进行阅读,直接就可以缓存到自己的手机里面。绝对不会出现任何的广告和弹窗,也可以导入更多https://www.juxia.com/sjwy/ruanjian-602769.html
17.《QURARE:MagicLibrary》更新后还有能登上的吗…前几天伴随着系统4.01升级,这个也更新了一个新版本,我现在loading到50%一直提示网络不稳定,更新前完全没问题?是不是需要微皮恩啊?QURARE: Magic Library PS4回答 本条答案已被采纳 moe_summer 1.可以进入2.解决办法 网络空闲段连(晚上凌晨貌似无法解决) 进度50%问题1.03 1.04都碰到过,每次升级版本都能碰到进度https://www.psnine.com/qa/7219
18.为什么我不能登录?(WhyCan’tILogIn?)为什么我不能登录?(Why Can’t I Log In?) 以下是登录图书馆账号或访问 PCC 图书馆文章和数据库时可能遇到的问题的原因。如果本页所列内容无法解决您遇到的特殊问题,请提交图书馆身份验证问题报告寻求协助。 用户名/密码丢失 这意味着可能出现下列问题之一:https://www.pcc.edu/library/help-in-your-language/help-in-chinese/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%B8%8D%E8%83%BD%E7%99%BB%E5%BD%95%EF%BC%9Fwhy-cant-i-log-in/
19.z今天登上去发现有募捐活动 点进去就是这个界面 目前用得最多的就是搜教材和看点别的小说,刚注册的账号是每天十本的限额,只下载书其实也够用,不过无限次下载以后写论文会比较方便。很纠结要不要捐,十美金换算成人民币也是要六十多块钱,而且不知道自定义金额可不可以无限额下载,可以的话我换个十块八块的也算是https://m.douban.com/group/topic/275385209/
20.南极游记南极,那片遥远的南方冰雪大陆阿蒙森船队 Photo credit toLibrary of Congress Washington D.C. 而他的竞争对手斯科特却没有那么顺利。由于没有充分估计到南极严酷的自然条件,对运输工具和探险队员的选择不当,特别是后勤补给出了问题,斯科特小队不得不用人力拖拽沉重的装备,消耗了大量的体力和时间。1912 年 1 月 17 日斯科特一行终于到达了南极https://www.mafengwo.cn/gonglve/ziyouxing/411780.html
21.立刻登录,赢取厚礼回馈:链接网址专属平台bob登不进去了 ag亚游国际集团 详情 ag百家乐靠谱网站 TDM澳门直播 详情 bet98下载 bjl必胜 详情 ios购彩app下载 leyu乐鱼的视频攻略 详情 ag平台客户端 cmp冠军首页 详情 ag体育赛事官网登录不了 gm电子 详情 cc国际集团彩球网 bb电子试玩网站APP 详情 ag8体育官网 aoa综合体育官方app下载 详情 bet体育足球现金网http://m.icuhmnt.cn/YHF/moa/yQCrzieZ.html
22.拉文:本赛季我出手超过20次的比赛不多我在出手选择上做得更好谈到本赛季自己的风格转变,拉文说道:“我不知道自己本赛季出手超过20次的比赛有多少,但肯定不多。很明显,当你出手次数减少时,你的得分就不会像以前那样多。如果你的使用率不够高,你的得分也会减少。但如何在比赛中依然保持影响力呢?我觉得我在选择出手时机、提高效率方面做得不错,但我觉得自己还能做得更好。”http://m.fzldmqk.cn/XEH/moa/ZMAnIW.html
23.16个全文文献免费下载神器,有你不知道的!Open AccessLibrary(OA图书馆)通过提供高质量的文档和快速响应的服务器,致力于为学术交流和进步做贡献。为大家提供200多万篇学术文章,这个数字估计在不久的将来还会增加。这里很多内容与PMC交叉。不过会收录部分没有进入pubmed的免费全文。 5、DOAJ (Directory ofOpen Access Journals) https://www.medsci.cn/article/show_article.do?id=7115640e854
24.登录?站点进入网站?专属NG官方下载,HW95508STC,ab体育娱乐app官方正版下载,98堂怎么登不进去,t娱乐娱乐官方网址乐彩网登录app,信彩app,B体育网页版在线入口,中国彩票能不能中10亿,中国彩经网app官方下载手机版ag捕鱼王手机版,esoccer足球电竞之战,97621国际游戏app入口,jrs低调看直播nba篮球,pg麻将胡了210万倍照片cp77彩票app安卓下载,http://m.dfgjsc.cn/20241215/5317.html
25.我的图书馆(上海图书馆暨中心图书馆一卡通行证)3)登录用户名(为网上注册所设置,或使用读者卡卡号登录“上图官网”(https://library.sh.cn)后在“个人中心”中设置的登录名,并非指用户的姓名) 2. 登录时的“密码”初始为线下/线上办理读者卡时或网上注册时所登记的线上办理读者卡时或网上注册时所登记的有效证件号。如果已在本平台中设置过登录密码,则日后https://passport.library.sh.cn/static/login_help.html