一、产生背景

在传统软件开发流程中,研发程序员将功能代码研发完成后,交由测试人员进行测试,最后通过运维人员部署上线。但是在这个过程中,常常因为环境问题、配置问题、软件版本问题等等诸多因素,造成一些问题。Docker技术的出现就是为了解决因部署实施而带来的一系列问题。

Docker技术实现了将开发环境、相关软件、配套环境等一系列研发环境打包成镜像文件,交由测试人员、运维人员使用。这样就减少了因部署而带来的一系列扯皮问题。除此之外,Docker提供了很多现成镜像,可以由用户直接使用,减少了一些中间件的安装。

总之,Docker方便了软件的安装部署,实现了一个镜像,多处复用的效果。

个人理解:
在固定服务器,固定服务的场景下,不需要使用Docker技术。因为开发环境,测试环境,上线环境,都是固定不变的。不管是开发,测试还是运维,都是基于固定的环境和软件开展工作的。
而对于一个服务,多处部署的应用场景,比较适合使用Docker技术。例如互联网大厂中,一个产品项目可能需要往全国甚至全世界多个机房中心中部署,那么这种场景就比较适合使用Docker技术。

二、什么是Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。

虚拟化容器:
Docker采用虚拟化容器技术,虚拟化容器是在操作系统层面实现虚拟化,直接复用本地主机的操作系统,而虚拟化出容器所需的资源。虚拟化出来的容器是容器所具备功能所需的最小资源,没用的功能和组件,不会出现在容器中。所以Docker容器具有体积小的特性。这也是为何Docker容器中输入很多linux命令不识别的原因。因为没用的组件和功能,容器中默认是不携带的。

虚拟化容器与虚拟机比较:
传统虚拟机技术是在硬件层面实现的虚拟化技术,它将虚拟化出来一套完整的操作系统。而Docker容器是在本地主机操作系统基础上,虚拟化出来所需功能组件的最小容器。因此,传统虚拟机技术所产生的镜像比Docker容器的镜像更大,更笨重。

三、Docker基本组成

前提条件

Docker要求运行在linux系统上,linux系统内核要求在3.8以上。在Centos系统上,要求centos7以上,64位操作系统。现在衍生出了Windows版本,其本质还是使用linux系统内核,只不过在Windows系统上模拟出了linux系统内核。

Docker由镜像、容器和仓库组成:

镜像

这里的镜像,和传统虚拟机中的.iso镜像,有异曲同工之处。传统虚拟机中的.iso镜像文件放在虚拟机中,可以创建出操作系统实例来。在Docker中的镜像,可以创建出Docker容器实例。上面说过,Docker容器并不是整个操作系统,而是所需功能的最小容器。
镜像就是一个模板,可以创建出很多容器实例。

容器

Docker镜像启动起来的每一个实例,都称之为容器。例如,redis镜像启动的容器,就是redis服务。mysql镜像启动的容器,就是mysql服务等。

仓库

存放镜像的地方,就是Docker的仓库。其机制类似于Maven仓库或git仓库。只不过存放的是Docker镜像。分为本地仓库和远程仓库。本地仓库就是宿主机本地存放镜像的地方。本地仓库没有的镜像,可以从远程仓库拉取。远程仓库分为公共远程仓库和私有远程仓库。公共远程仓库有Docker Hub或阿里云仓库。私有远程仓库就是公司 内部自己搭建的Docker仓库。私有远程仓库可安装Docker registry软件进行搭建。具体操作这里不再记录。Docker仓库运行流程如下:

我们自定义的镜像,也可以上传到远程仓库,供别人拉取使用。阿里云仓库是付费的。
甜点: 在个人安装Docker的宿主机上,可配置阿里云提速器,来加快镜像的远程拉取速度。这里注意要区分与配置阿里云远程仓库地址。配置阿里云远程仓库地址可以用来加快拉取速度,因为Docker Hub是国外网站,拉取速度较慢。而这里 说的配置阿里云提速器,是在配置了阿里云仓库后,更进一步的提速效果。具体的配置方式是登陆自己的阿里云账号,然后搜索容器镜像服务,然后点击此选项,然后选择镜像提速器菜单,安装上面操作配置即可,如下图所示:

可以看出这是跟个人账号挂钩的一个操作,在个人学习时,可以配置使用。

四、Docker基本操作命令大全

系统级别命令

镜像相关命令

  1. 查看本地仓库镜像:
docker images

输出字段及含义如下图:


其中一个镜像可以有多个TAG版本存在。使用某个版本,可以通过镜像名称:TAG来指定。当版本为latest时,可以省略:TAG。否则必须使用镜像名称:TAG

  1. 查询远程仓库镜像:
docker search xxx

可以列出镜像,如下图所示:

其中OFFICAL代表是否官方。优先选择官方镜像进行拉取。这里只是搜索镜像,并不包含具体版本号,一般镜像包含了各个版本。我们可以直接在镜像名后面加我们想要的版本即可。如果不加版本,默认拉取latest版本。
在Docker Hub官网,也可以搜索某个镜像。

  1. 拉取镜像到本地:
docker pull 镜像名字[:TAG]

如果不加TAG,默认拉取最新的。

  1. 删除镜像:
docker -rmi 镜像名字ID

镜像启动的所有实例必须停止运行才可以删除镜像。

容器相关命令

  1. 启动容器命令:
docker run

参数:

--name xxx   #指定容器名称为xxx
-d #后台运行,并返回容器ID,此方式开启容器后不进入容器
-it #其实是-i和-t两个参数,一般都在一起使用,开启交互式容器,启动容器后进入容器内部
-p 宿主机port:容器port  #指定宿主机端口与容器端口对应关系。可在宿主机上通过此端口访问容器服务
-v 宿主机路径:容器内部路径  #将容器内部某个路径挂载到宿主机上,实现数据的同步和持久化
  • 后台启动容器命令:
 docker run -d -p 1000:1000 --name 容器名称 镜像ID(镜像名称:TAG)
  • 交互启动容器命令:
docker run -it -p 1000:1000 --name 容器名称 镜像ID(镜像名称:TAG) /bin/bash

在交互式容器启动时,需要在命令后面加上/bin/bash或bash命令,这样才能进入容器内部,与容器内部进行交互。这点需要特别注意。

退出容器:
交互式进入容器后,如果退出容器到宿主机呢?两种方式:
ctrl+D或exit命令退出容器,容器也会停止。
ctrl+p+q退出容器,容器不会 停止。

文件挂载:
在容器中的数据,会随着容器的删除而删除,而且容器中配置文件的修改,需要先进入容器才能修改。使用文件挂载参数-v,将容器内文件与宿主机文件进行映射后,容器内文件和宿主机映射文件就会保持同步,在宿主机修改配置文件,容器内 对应配置文件也会修改(容器重启后生效)。在容器内产生的数据,在宿主机映射文件也会产生相应数据。
例如在redis容器或mysql容器中,都需要将配置文件和数据文件进行挂载,一个是便于配置文件的修改,一个是对redis日志或mysql数据进行持久化保持。
挂载命令:

docker run -d --privileged=true -v 宿主机绝对路径:容器绝对路径 镜像名

其中--priviledge=true是授权参数,最好 加上,否则有时会出问题。
2. 查看容器实例命令:
查询正在运行的容器实例:

docker ps

查看正在运行和已经停止的容器实例:

docker ps -a

这里需要注意,当用某个镜像启动容器后,容器就会在宿主机存在。即使这个实例停止运行了,那么这个容器还是存在的,我们可以继续启动这个容器。

  • 启动某个容器命令:
docker start 容器ID

关闭某个容器命令:

docker stop 容器ID

删除容器命令:

docker rm 容器ID

删除容器后,容器才会在宿主机消失。删除容器是rm,删除镜像是rmi,其中这个i就代表image镜像的意思。

  1. 进入某个容器命令
    上面讲到启动一个后台运行的容器,那么如果 想进入这个容器做交互,应该如何进去呢?执行以下命令:
docker exec -it 容器ID  /bin/bash

退出按ctrl+D退出即可,因为是后台运行启动的,这样退出也不会停止容器运行。

还有一个进入容器内部的命令:

docker attach 容器ID

这种方式很少用,原因如下:

3. 查看容器详情命令:

docker inspect 容器ID

返回json格式容器详情信息,内容很多,如下所示:

[{"Id": "3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f","Created": "2022-08-28T06:55:02.245198929Z","Path": "docker-entrypoint.sh","Args": ["redis-server"],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 21683,"ExitCode": 0,"Error": "","StartedAt": "2022-08-28T06:55:04.16474428Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:3edbb69f9a493835e66a0f0138bed01075d8f4c2697baedd29111d667e1992b4","ResolvConfPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/resolv.conf","HostnamePath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/hostname","HostsPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/hosts","LogPath": "/var/lib/docker/containers/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f/3d25328ac0bbab7525caadf322e1df54ef6ca776f258f6c415f6019d1514824f-json.log","Name": "/keen_noether","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"CgroupnsMode": "host","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": [0,0],"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/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879-init/diff:/var/lib/docker/overlay2/8c626981a567a606070bdc8e00a103eed11d0859dcfce2763b37a4f2e257b668/diff:/var/lib/docker/overlay2/c19216a0ddf38928401b118816cda02bd497603ec3109647bd147eabef3c2dd8/diff:/var/lib/docker/overlay2/2d98fdbbe975db2295a238830f740242863eb62834e1c1288e9096f88aea17b6/diff:/var/lib/docker/overlay2/df05555cfad1eec6219f2cb14ec183be109d09f04a4a245dd755b619551492b8/diff:/var/lib/docker/overlay2/40df4c9e096704ba37d1e916faf0f02a012bd061b6883de5a3c12699b2f30e41/diff:/var/lib/docker/overlay2/f12fbd3a76a4f40e20699b214a894a19c32d6650b3824ed7fb7f47876531866d/diff","MergedDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/merged","UpperDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/diff","WorkDir": "/var/lib/docker/overlay2/ef1cb55fe9ba3130296f2cecc676be442e78e76524b2b58a1ba0ef58aac39879/work"},"Name": "overlay2"},"Mounts": [{"Type": "volume","Name": "9bd2c45c0f4711a8291c6eb4a2607aa20f9e23b402facef0be854925dfbba76f","Source": "/var/lib/docker/volumes/9bd2c45c0f4711a8291c6eb4a2607aa20f9e23b402facef0be854925dfbba76f/_data","Destination": "/data","Driver": "local","Mode": "","RW": true,"Propagation": ""}],"Config": {"Hostname": "3d25328ac0bb","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"ExposedPorts": {"6379/tcp": {}},"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","GOSU_VERSION=1.14","REDIS_VERSION=7.0.4","REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-7.0.4.tar.gz","REDIS_DOWNLOAD_SHA=f0e65fda74c44a3dd4fa9d512d4d4d833dd0939c934e946a5c622a630d057f2f"],"Cmd": ["redis-server"],"Image": "redis","Volumes": {"/data": {}},"WorkingDir": "/data","Entrypoint": ["docker-entrypoint.sh"],"OnBuild": null,"Labels": {}},"NetworkSettings": {"Bridge": "","SandboxID": "adfae3e2a0fae1e742453439bfe09024f92eb951b72eb4e363b965ff913c9c75","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {"6379/tcp": null},"SandboxKey": "/var/run/docker/netns/adfae3e2a0fa","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "2a3d532504abe9f43339fb9cd9e8021a726641819e7ce25e7c0ac4148a6bb925","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:02","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "7667f6780a0f4b166b8487b3eca53cd6754fb92d16d599283ca3129f35c3a808","EndpointID": "2a3d532504abe9f43339fb9cd9e8021a726641819e7ce25e7c0ac4148a6bb925","Gateway": "172.17.0.1","IPAddress": "172.17.0.2","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:02","DriverOpts": null}}}}
]

其中包含了容器的网络模式,ip,镜像,状态,挂载情况(Mounts)等等信息。总之容器的全部信息都可以在这里找到。
4. 其他容器命令

  • 查看容器日志命令:
docker  logs  容器ID

此命令在后台运行容器时使用,可以查看容器内服务运行日志。特别是容器运行失败或容器内服务出现问题时,可以通过该命令快速浏览容器软件所产生的日志。

查看容器内部进程:

docker top 容器ID

复制容器内文件到宿主机:

docker cp 容器ID:容器内文件路径   宿主机存放文件路径

五、Dockerfile

什么是Dockerfile

上面我们讲到可以从远程仓库拉取现成的Docker镜像。那我们该如何制作自己的镜像呢?比如我们的项目打成jar包,在jdk里运行,想要把jdk环境和jar包制作成一个镜像,供其他人通过Docker进行运行,该如何做呢?这就用到了Dockerfile技术。

Dockerfile是构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

Dockerfile就是基于某个基础镜像,对镜像的一个增强脚本。比如,基于centos镜像,要安装jdk8环境,并且要运行我们项目的jar包。或者往centos镜像中添加ifconfig命令的功能,或者vim命令的功能。这都算是对基础镜像的一个增强。通过编写Dockerfile脚本文件,构建出一个新的镜像,包含上述的增强功能。

构建Dockerfile三步曲

  • 编写Dockerfile文件
  • 使用Dockerfile文件构建镜像
  • 运行生成的镜像容器

如下图所示:

Dockerfile语法指令

上面提到Dockerfile是一个脚本文件,用来构建镜像增强。docker定义了Dockerfile的一些关键字指令(保留字指令)。这些指令特性如下:

下面看都有哪些指令:

  • FROM:
    指定加强镜像是基于哪个镜像做加强的。写在Dockerfile第一行。基于哪个镜像,用镜像名称:TAG表示即可。
  • MAINTAINER:
    Dockerfile作者和邮箱地址,可选项
  • RUN:
    用Dockerfile文件构建镜像时执行的命令,支持shell格式和exec格式两种。一般使用shell命令。在docker build构建镜像时执行RUN 后面定义的shell命令。
  • EXPOSE:
    容器服务对外暴露的端口。如tomcat镜像暴露8080端口,就是容器中tomcat暴露的端口。
  • WORKID:
    指定交互式进入容器后默认到达的目录,一个落脚点。
  • USER:
    指定镜像以什么用户来执行,如果不指定,默认是root用户。
  • ENV:
    用来构建镜像过程中设置环境变量。以k v形式定义。例如: ENV MYPATH /usr/local/tomcat表示设置MYPATH环境变量为/usr/local/tomcat。在Dockerfile中,就可以使用$MYPATH来代表这个路径。
  • VOLUME:
    容器数据卷,用于保存和持久化工作。等同于docker run -v 参数,在这里定义后无需在容器启动时指定了。
  • ADD:
    将宿主机文件拷贝到容器中,并解压。即宿主机中压缩文件拷贝到容器后,会自动解压出来。默认拷贝Dockerfile同级目录下的文件。所以要将Dockerfile文件和要拷贝进容器的文件放在同一个目录下。
  • COPY:
    类似于ADD命令,只不过没有自动解压功能。一般使用ADD命令。
  • CMD:
    定义在容器启动后,执行的命令。也是支持shell格式和exec格式。
    CMD [“可执行文件”,“参数1”,“参数2”…] 在容器启动后,执行shell命令,一般用于启动容器中的服务。例如tomcat容器中定义CMD命令,就是在tomcat容器启动后,执行CMD后面的命令,启动tomcat服务。
    Dockerfile文件中可以定义多个CMD命令,但只有最后一个生效。CMD会被docker run后面的参数替换。替换是当docker run后面的参数与CMD指令的作用相冲突时,以指令参数为准。当作用不冲突时,是叠加效果。

需要注意的是,RUN指令后面的shell脚本是构建镜像时执行的命令,CMD指令是容器启动后执行的命令。

  • ENTRYPOINT:
    也是在容器启动时执行命令,类似于CMD。与CMD的区别是ENTRYPOINT不会被docker run后面的命令所覆盖(不理解这句话含义)。命令格式: ENTRYPOINT [“可执行文件”,“参数1”,“参数2”]。


ENTRYPOINT 作为启动容器的运行命令时,CMD命令就不再是运行命令了,而是ENTRYPOINT的一个参数。如上图例子,衍生出来的命令其实就是 nginx -c /etc/nginx/nginx.conf。其中nginx -c 是ENTRYPOINT命令,其是不会被用户后续追加命令覆盖的,后面的/etc/nginx/nginx.conf是CMD命令,其不再是运行命令,而是参数命令。而且它也保留CMD特性,会被后面的CMD命令所覆盖。如用户自定义了 -c /etc/nginx/new.conf后就将之前CMD命令覆盖了。

tomcat Dockerfile文件查看

在Docker Hub上搜索tomcat镜像,并选择第一个搜索结果(官方镜像),点进去后,选择自己想要查看的版本,如下图所示:


这里看Dockerfile脚本文件的最后两行:

可以看到,tomcat容器暴露出来端口是8080,且容器启动后,执行catalina.sh命令。这就是启动tomcat服务的命令。所以启动tomcat镜像后,tomcat也就自动启动了。

注意:
当以交互式启动tomcat镜像时,不要加/bin/bash命令,因为这样会覆盖掉最后的CMD命令。这样就不会执行tomcat启动命令。这样容器 虽然启动了,但是tomcat没有运行。所以遇到这种情况时,就不要以交互式方式启动了,先以后台方式启动,然后再进入容器内部。

Dockerfile构建镜像

命令:

docker build -t 新镜像名字:TAG

构建好的镜像自动进入docker本地镜像仓库,并不会生成具体某个可看见的文件。其中TAG版本号自己定义即可。定义好容器后启动容器即可。

Docker执行Dockerfile的大致流程如下:

  1. docker从基础镜像运行一个容器
  2. 执行每一个指令对基础镜像进行修改
  3. 执行类似docker commit命令提交一个新的镜像层
  4. docker再基于新镜像运行一个新容器
  5. 执行Dockerfile下一条指令直至执行完毕。

虚悬镜像

在使用Dockerfile构建镜像时,有时会出现虚悬镜像。所谓虚悬镜像就是镜像名称和TAG都是none的镜像。虚悬镜像产生的原因可能是Dockerfile在一层一层的生成新的镜像时,所产生的垃圾镜像,没有用,直接删掉即可。

六、网络模式

查看网络模式命令:

docker network ls

docker默认网络模式有如下三种:

bridge桥接模式

桥接模式是最常用的模式,也是默认模式。Docker服务会默认创建一个docker0网桥,如下图所示:

这样,每一个容器都会有自己的一个ip,ip网段和docker0的网段一样。这样就可以实现容器之间,容器与宿主机之间的通信。如下图所示:

其中,docker0是网桥,起到交换机的作用。网桥ip一般为172.17.0.1。容器ip为172.17.0.2等等。需要注意的是,容器每次重启后,ip都不是固定的,是随机变化的。

Host模式

想使用Host模式,在docker run命令后加参数–network host或-net host即可。使用host模式,容器ip和端口用宿主机ip和端口就行。Host模式容器详情中网络模式如下:

自定义网络模式

docker支持自定义网络模式。我们除了上述几种网络模式外,我们可以自定义网络模式,命令如下:

docker network create 网络名称

自定义创建的网络模式,本质还是用桥接模式。只不过网络名称是自己定义的。那么自定义网络模式有何作用呢?
自定义网络模式是为了解决容器每次启动后,ip都会变化造成的问题。例如我们在连接数据库,redis时,配置文件写ip地址进行连接。当容器重启后,ip变了。那么数据库就连接不上了。
容器使用自定义网络后,就可以通过容器名称进行容器的连接了。当连接mysql容器,redis容器的服务与mysql容器、redis容器都在同一个自定义网络时,就可以通过写容器 名称来代替ip地址,进行mysql和redis的连接。这样就规避了ip变化带来的问题。
需要注意的是,所有的容器必须都在一个自定义网络中,且启动容器时必须通过 --name指定容器名称。如果不指定名称,docker自动生成的名称也不能通过容器名称访问。虽然自定义网络也是桥接模式,但是使用默认的桥接模式是不能通过容器名访问的。

七、Dockerfile创建jar包镜像

jdk8镜像制作

首先,基于centos基础镜像制作jdk8镜像,编写Dockerfile文件:(Dockerfile文件和jdk8安装包需要在同一目录)

vim Dockerfile
FROM centos:7ENV MYPATH /usr/local
WORKDIR $MYPATH#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径,jdk包和Dockerfile文件必须同一个目录下
ADD jdk-8u281-linux-x64.tar.gz /usr/local/java
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_281
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATHEXPOSE 80CMD echo $MYPATH
CMD echo "success"
CMD /bin/bash

jar包镜像制作

基于上述制作好的jdk8镜像,制作jar包镜像:(Dockerfile文件和jar包需在同一目录下)

vim Dockerfile
FROM centosjava8:1.5
MAINTAINER xiaoxiaosu
#VOLUME指定临时文件目录为tmp,在主机/var/lib/docker目录下创建一个临时文件并连接到容器的tmp
VOLUME /tmp
ADD gulimall-product-0.0.1-SNAPSHOT.jar gulimall-product-0.0.1-SNAPSHOT.jar
#运行jar包
RUN bash -c 'touch gulimall-product-0.0.1-SNAPSHOT.jar'
ENTRYPOINT ["java","-jar","gulimall-product-0.0.1-SNAPSHOT.jar"]
EXPOSE 10001

八、Docker-Compose技术

简介

Docker-Compose是Docker官方开源项目,负责对Docker容器集群的快速编排。需要编写一个docker-compose.yml文件,在里面通过命令管理多个Docker容器,管理多个容器之间的协调,来共同服务于一项项目。通过docker-compose.yml进行多个容器的一键启停操作。

docker-compose需要单独安装。可参考文章:docker-compose教程(安装,使用, 快速入门)

使用步骤

1.编写Dockerfile并构建各个微服务镜像
2.使用docker-compose.yml定义一个完整的业务单元,安排好整体应用程序中各个容器服务
3.执行docker-compose up命令,一键启动项目

compose相关命令

docker-compose.yml文件编写

详细配置可参考文章:docker-compose.yml的详细解释与说明
下面是一个自己练习的demo:

version: "3"
services:microService: #实例名称,随便定义,不重复就行image: gulimall_productcontainer_name: ms01 #容器名称,不写这个参数默认就是microServiceports:- "10001:10001"volumes:- /app/microService:/datanetworks:- ceshidepends_on:- redis#以上命令相当于写了一个docker run命令:docker run -d -p 10001:10001 -v /app/micorService:/data --network ceshi --name ms01 gulimall_product:latestredis:image: redisports:- "6379:6379"volumes:- /app/redis/redis.conf:/etc/redis/redis.conf- /app/redis/data:/datanetworks:- ceshicommand: redis-server /etc/redis/redis.conf

写完yml文件后,通常执行下面命令检查编写的yml文件是否有问题:

docker-compose config -p

如果没有任何输出,代表编写yml文件没问题。在docker-compose.yml中都规定同一个自定义网络模式,在就可以使用服务名进行通信了,如mysql连接,redis连接等,都可以使用docker容器实例名配置。

一键部署,一键启停,十几个二十几个docker实例用docker-compose编排就可以。再多了就考虑引入K8s。中小型公司用docker-compose足够了。

九、监控统计

轻量级使用Portainer监控工具进行监控。docker用命令能完成的工作,都可以使用Potainer工具进行图形操作,例如拉取镜像,启动容器,查看容器详情,查看网络等等,总之一切可以用命令完成的操作,都可以用Portainer图形操作完成。

重量级的健康使用CAdvisor+InfluxDB+grafana进行监控。但是需要用到重量级监测的体谅的项目,直接使用K8s了,所以很少使用Docker的这个监控。

Docker基础入门详解相关推荐

  1. Docker基础03--Dockerfile详解与镜像发布--(狂神说docker学习笔记)

    文章目录 1. Dockerfile介绍 2. Dockerfile指令说明 3. 制作Centos镜像 3.1 编写Dockerfile的文件 3.2 通过这个文件构建镜像(注意最后加个点!!!) ...

  2. 企业版Docker2——Docker基础命令详解

    记住:容器是基于镜像的,就像虚拟机也是基于镜像一样的 1.常用的Docker基础命令总结 2.命令的详细说明与演示 (1)docker create docker create 命令为指定的镜像(im ...

  3. Gradle安装部署与基础入门详解

    [1]Gradle简介 Gradle 是一款Google 推出的基于JVM.通用灵活的项目构建工具,支持Maven,JCenter 多种第三方仓库;支持传递性依赖管理.废弃了繁杂的xml 文件,转而使 ...

  4. 【世界上最好用的编程语言】PHP基础入门详解

    简介 PHP(超文本预处器)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域.PHP 独特的语法混合了C.Java.Perl以及PHP自 ...

  5. docker portainer_Docker入门详解(十一) 图形Portainer

    一.介绍    Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台操作.S ...

  6. python文件输入符_python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)...

    一.变量和表达式 >>> 1 + 1 2 >>> print 'hello world' hello world >>> x = 1 >&g ...

  7. python循环控制语句将数值转化成字符串_python基础入门详解(文件输入/输出内建类型字典操作使用方法)...

    f=open("foo.txt") line=f.readline() while line: print line, line=f.readline() #读取一行,包括换行符' ...

  8. 【基础入门详解】程序员的二维码也要玩出不同色彩,用Python生成动态彩色二维码

    一.前言 常见的二维码为QR CodeCode,QR全称是Quick Response,是一个近几年来移动设备上超流行的一种编码方式.它的结构如下: 主要有以下特点: 符号规格从版本1(21×21)到 ...

  9. dockerk8s入门详解

    docker&k8s入门详解 一.Docker 1.1 什么是Docker 1.2为什么要使用docker? 1.更快速的交付和部署 2.更高效的虚拟化 3.更轻松的迁移和扩展 4.更简单的管 ...

最新文章

  1. Redis 高级教程 Redis 基准(3)
  2. 在Anacoda中管理多个版本Python
  3. 【8】青龙面板系列教程之nolanjdc的一键安装获取cookie【作者删库了,不用尝试了】
  4. bond-vlan-bridge
  5. 阿里工程师总结的《MySQL 笔记高清 PDF 》 开放下载
  6. AppWidget应用(一)---创建一个appWidget
  7. 腾讯 AI Lab 联手迈瑞医疗,助力血液病筛查与体外诊断
  8. C# ASP.NET B/S模式下,采用lock语法 实现多用户并发产生不重复递增单号的一种解决方法技术参考...
  9. 杭州SEO大熊:百度分享插件的SEO研究心得
  10. 经典的Fisher-Yates Shuffle算法
  11. 【smart-transform】取自Atom的babeljs/cs/ts智能转es5 库
  12. TEM:基于树模型构建可解释性推荐系统
  13. DRF + react 实现TodoList
  14. 【linux运维】linux运维常用工具有哪些?
  15. 算法竞赛入门经典(第2版)—索引
  16. 计算机四级网络工程师总结
  17. C++A类继承B C类_长期投资指数基金到底选择A类收费还是C类收费
  18. JN项目-qq昵称含有表情无法进行第三方登录
  19. 5款最好的安卓界面设计工具推荐
  20. logo设计的30种技巧

热门文章

  1. 1234变4321java_java:把1234成4321整数倒逆代码
  2. 调皮捣蛋的孩子--十大负面测试用例
  3. laravel 上传图片
  4. 管理手记:和上司相处不要太“学生气”
  5. 004 鸿蒙应用开发-通知栏
  6. 离散数学 数学三大危机
  7. 2022-2027年中国知识产权代理行业发展前景及投资战略咨询报告
  8. Rasa项目实战之银行金融Financial Bot智能业务对话机器人业务功能微服务解析与调试(九十二)
  9. 基于单片机智能婴儿车控制设计(毕业设计)
  10. 华东院进入华为智慧战略 其他院怎么办