Docker知识点总结

一. 什么是Docker

        在docker的官方之什么是docker中提到了一句话:“当今各大组织或者团体的创新都源于软件(例如OA、ERP等),其实很多公司都是软件公司"。用户量的激增导致了并发、指数级增加的数据、应用的可靠性等问题,单体应用已经应对不了这些问题,于是诞生了分布式、集群、微服务、边缘计算等各种名词、架构风格和满足这种架构风格的各种框架,那我们接下来跟大家谈谈这些技术名词。

         分布式:将一个复杂的应用按照模块进行拆分,每个拆分的模块做成一个应用,分开部署,分开运行,各个模块之间通过webservice、http rest、rpc的方式进行调用。但是分布式系统中面临着很多棘手的问题:1. 如果某一个应用crash掉了,会导致调用该模块的其他模块也无法正常工作;2. 因为网络抖动或者硬件的问题导致数据的一致性问题(即分布式事务问题);3. 运维和硬件成本的急剧上升。

        集群:集群是指将某一个应用或者某个模块部署在多台机器上(这些机器上跑的代码是相同的),然后通过负载均衡的方式让每个应用都能处理请求,即使某一个应用宕掉了,其他的应用一样可以处理请求,集群是为了解决我们上面提到的分布式应用中的第一个问题,但是集群也面临着诸多的问题:1. 运维和硬件成本的急剧增加;2. 实现集群势必会引入第三方的插件,那么第三方插件如何去保障其稳定运行;

          微服务:微服务只是一种架构风格,最早是由Martin Fowler(博客点击这里)提出,他对微服务的解释是:In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies(简而言之,微服务是一种架构的风格,将每一个单独的应用来作为一个服务套件,每一个服务套件运行在其独立的进程当中,使用轻量级的方式相互调用,通常采用HTTP的方式。这些个服务是要建立在业务能力和自动化独立部署的基础上的。这些服务间应该以一种去中心化的方式运行,而且这些服务可以使用不同的语言、不同的存储机制来实现)。我用自己的话来表达一下,所谓的微服务就是将一个可以独立部署、业务能力独立的应用,应用之间耦合度尽量降低(只能尽量降低,不可能实现绝对的解耦),尽可能的去中心化。微服务也同样的面临着诸多的问题:1. 分布式事务问题;2. 运维和硬件成本急剧上升。

        边缘计算:首先跟大家说一下,为什么要在这里提到边缘计算呢?因为本文讲的是docker, docker中提到了边缘计算。所谓的边缘计算是指在接近数据源的地方进行数据的处理,而不是将数据集中到一起进行处理,边缘计算可以实现数据的实时分析,将有价值的数据过滤后丢给云端。下面给一张图方便大家的理解:

我们在回到本节标题“什么是docker”,我们在介绍完上面这些名词后,会发现无论当今所流行的不论是分布式、集群还是微服务都面临着一个问题:运维和硬件成本的急剧上升。那么docker的出现就是为了解决这个问题:解决运维和硬件成本的问题。

  提到这里结合自己的工作经历跟大家讲解一下我以前在某家公司是如何解决这个问题的,我们公司购买一台服务器,然后在服务器上虚拟出多个计算机,然后在虚拟的机器上部署我们的应用,所谓虚拟机是借助于一些软件虚拟出一台和我们的物理机一样的机器,也有CPU、内存、硬盘、光驱等。虽然我们可以在一台真实的物理机上虚拟出多台机器,但是每个机器上其实都是有一套完整的操作系统,那么多台虚拟机上就有多套操作系统,这些操作系统也是要消耗物理机的资源的,那么如何解决这个问题呢?这同样回到我们该节的主题“什么是docker”。

二. Docker的优点

其实这个问题,我们在第一节“什么是docker”这个章节已经给出了答案。在本节我们会给出系统的总结:

2.1 资源的复用

      上节笔者说到我们公司在解决运维和机器成本问题的时候说到,通过传统的虚拟机的方式每一台虚拟机都有一套完整的操作系统,那么我们能不能就使用一个操作系统,每个隔离的进程只运行我们的应用和所依赖的第三方软件,docker恰恰可以解决这个问题。

2.2 一致的环境

      我相信做过开发的朋友都有这样的经历,我们在本地开发一个应用,尤其是分布式应用,我们需要在本地安装多台虚拟机,在本地测试各种功能完好。接着修改各种参数后辛辛苦苦部署到测试机上后,测试的同事经过紧张、严谨的测试,一切都那么的prefect。当我们高高兴兴的修改完各种参数后部署到生产环境,我嘞个擦,各种问题都出现。开发人员经常挂在嘴边的几句话“昨天我跑着还是好好的呀”,“测试的时候还是好好的呀”,导致开发人员说这些话的原因是因为开发、测试、生产环境的不一致所导致的。docker也可以解决这个问题,docker的镜像提供了除内核以外完整运行环境,确保的环境的一致性。

2.3 启动速度更快

      以往的虚拟机的方式启动的时候需要的时间会很长,因为要启动操作系统,可能需要几分钟甚至更长。但是docker启动只需要几秒、几毫秒。

2.4 应用的迁移

      给朋友举个例子,以前你的应用部署在阿里云上,那么那天你的领导需要将应用签署到腾讯云上,使用docker的话,会变得非常的简单。

三. Docker的安装

Docker安装步骤的官网地址:https://docs.docker.com/install/linux/docker-ce/ubuntu/

3.1配置仓库

yum install -y yum-utils \

  device-mapper-persistent-data \

  lvm2

3.2 开始安装

配置docker的下载源

yum-config-manager \

   --add-repo \

   http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装docker

yum -y install docker-ce docker-ce-cli containerd.io

3.3  验证docker是否安装成功

docker -v       #查看docker的版本信息

docker info     #查看docker的基本信息,例如多少镜像,多少个容器等

docker help    #查看docker命令

四. docker镜像与容器

docker的镜像与容器是docker中两个至关重要的概念,首先给各位读者解释一下这两个概念。镜像,我们从字面意思上看,镜子里成像,我们人站在镜子面前,在镜子中会呈现一个完整的我们(包括我们的着装、表情、发型等等)。那么在软件领域的镜像是指对数据按照一定的格式的一个完整的拷贝;容器是镜像运行时的实体,比如说镜像是个类,当没有被加载的时候,它是存放在我们的硬盘上的,而容器是对象,对象只有在程序运行的时候才会被创建,并且一个类可以创建N多个对象,对应到我们的镜像与容器,一个镜像可以用于创建多个容器,每个容器运行在各自的namespace中间。

镜像是对文件的副本,能被特定的软件或者硬件锁识别。

在本节我们粗略的说一下镜像,重点在于讲解容器,因为容器一定要用到镜像,所有我们又不得不提,会有专门的篇章来介绍镜像。

4.1 镜像仓库的配置

所谓的镜像仓库就是镜像集中存放的位置,docker默认的镜像仓库地址是 https://hub.docker.com,由于该地址服务器不在内地,访问的速度可能会有一定的影响。所以我们会经常将docker默认的镜像仓库换成阿里巴巴或者163的镜像仓库地址,以便加快我们的访问速度,本小节我们以阿里巴巴的镜像仓库为例为大家讲解。

A. 注册阿里云账户,地址为:https://account.aliyun.com/login/login.htm

B.进入到阿里云控制台,选择“容器镜像服务”

C.进入到“镜像加速器”,在右侧会出现“加速器地址”以及如何配置加速器地址

D. 在 /etc/docker/目录下是没有 daemon.json文件的,所有你要进入到 /etc/docker/ 目录下执行 touch  daemon.json  命令创建 daemon.json文件,如下图所示:

E.在新创建的daemon.json文件中加入如下内容

{

  "registry-mirrors": ["https://zbhswmwr.mirror.aliyuncs.com"]

}

F.执行如下命令

sudo systemctl daemon-reload                  #重新加载守护进程

sudo systemctl restart docker                 #重启docker

4.2 docker镜像的基本命令

A.查看docker本地有多少镜像:docker images

B.拉取镜像仓库的某个镜像:docker pull 镜像名:tag,例如:docker pull hello-world:linux

C.只查看镜像的ID: docker images -aq

D.删除一个镜像: docker rmi 镜像名[:tag]  或者  docker rmi 镜像ID   

五. 容器的基本命令

A. 容器的启动:docker run 镜像名:tag 

B.查看正在运行的容器:docker container ls 或者 docker ps 或者 docker ps -n 2

注:docker ps -n 2表示查看最近运行或者运行过的两个容器。

C.查看所有的容器,包括已经停止了的容器:docker container ls -a 或者 docker ps -a

D.以交互的方式启动容器,例如我们启动一个centos容器:docker run -i -t centos

  注意:-t的是宿主机分配一个终端,并将该终端绑定到标准的输入上;-i让容器的标准输入保持打开状态。二者都是联合在一起使用的。

如果以上述的方式启动centos容器,那么我们如何回到我们的宿主机呢?有两种方式:

            1). 执行 exit 命令,该命令会关闭容器,然后退出。

                  2).按住ctrl + p + q, 容器不关闭,只是退出。

E.以后台进程的方式启动容器:docker run -d centos

细心的你一定会发现,我们以守护进程的方式启动容器后,容器却已经退出了(status为Exited)。原因是因为docker容器启动后必须要有一个前台进程,说白了就是一直要有事情干,那么怎么能让他有事干了,我们可以开启一个一直挂起的命令,例如:top tail,否则就会自动退出。那么有什么解决方法呢?其实这个问题解决的方法笔者搜集到三种(都是在网上查找的):

1).以交互的方式启动容器,然后通过ctrl + p + q 不关闭容器退出容器,这种方式在上面已经给大家提到过:

docker run -it centos

  2).通过一个死循环间歇性的不停的输出一个字符串 :

docker run -d centos /bin/bash -c "while true;do echo hello world;sleep 2;done"

        3).通过我们上面提到过的top命令的方式开启一个前台进程,让容器有事情干:

docker run -d centos /usr/bin/top -b

F.容器的停止,容器的停止有两种方式:1.docker stop 容器ID;2.docker kill 容器ID。方式一是一种平滑、优雅的方式关闭容器;方式二是暴力的方式关闭容器。

G.删除容器:docker rm [-f] 容器ID。-f表示强制删除,正在运行的容器用该命令。

H.查看容器的日志:docker logs -t -f 容器ID。-t是显示日志的时间,-f是监视日志的增长。

I.重新进入已经退出的容器:docker attach 容器ID

J.不进入到容器,直接通过命令操作容器:docker exec 容器ID ls -l / 

启动mysql的命令:

docker run --name myMysql -e MYSQL_ROOT_PASSWORD=7890 -p 3307:3306 -d mysql:5.7.27

备注:启动mysql容器,指定容器名为myMysql,指定root的密码是7890,将宿主机的3307端口映射到mysql容器中的3306端口。

Docker进阶

一. 数据卷(volume)

1.1 为什么需要数据卷

docker镜像是由多个文件系统(只读层)叠加而成,当我们启动一个容器的时候,docker的服务端会加载镜像的只读层,并在最顶层创建一个可读写层。当运行的容器修改现有的文件,该文件会从只读层拷贝到读写层,其实并没有影响到镜像本身,依然存在于镜像中。当我们删除掉容器,容器运行时的数据都会丢失,当我们通过镜像重新run一个容器,该容器还是会回到最初的状态。那么问题来了,我们该如何保存我们运行中的数据了?这个问题有两种解决方法:a. 我们可以定期的将我们的容器通过commit的方式生成一个镜像;b.通过数据卷来实现。很明显我们不可能不停的commit来生成镜像,有些朋友可能会说你这么说的意思是通过数据卷来实现呗,可我都不知道什么是数据卷,怎么知道它好用了?那么接下来我们就开始来介绍数据卷。

1.2 什么是数据卷

数据卷就是容器内部的数据目录直接映射到宿主机上的目录上,无论在宿主机还是容器内对数据的修改在另外一方都是可见的。

1.3 数据卷的使用

1.3.1 命令的使用

我们还是通过前面篇章中使用的centos镜像来讲解,其实也就一个命令,我们的工作也就是围绕着该命令来讲解:docker run -it -v /dataVolumn:/containerDataVolumn centos


 至于其他的命令在这里不作过多的解释,只解释一下 -v /dataVolumn:/containerDataVolumn 这个命令的意思,-v是绑定将容器中的目录挂载到宿主机的目录上,/dataVolumn:/containerDataVolumn中冒号前的路径是指自动在宿主机上创建的目录名(不用我们手动去创建),冒号后的路径是指在容器中自动创建的目录名。

1.3.2数据卷的创建与测试

我们前面提到过“论在宿主机还是容器内对数据的修改在另外一方都是可见的”,那么本小节我们回来测试这个问题。

A.我们在容器中 /containerDataVolumn 目录下创建一个container.txt文件,并写入内容,命令:echo "hello world" > container.txt

在宿主机的 /dataVolumn目录下会查看到有container.txt文件,并查看内容,如下图所示:

B.在宿主机的 /dataVolumn目录下新建 host.txt文件,并写入内容,命令为:echo "welcome" > host.txt

在容器的/containerDataVolumn目录下会看到host.txt文件,并查看内容,如下图所示:

C.删除掉容器,查看宿主机 /dataVolumn目录,文件并没有丢失

D.我们可以通过 docker inspect 容器ID 命令查看容器的信息,其中hostConfig.binds可以查看到绑定信息,如下图所示:

1.3.3 数据卷的其他创建方式

通过上面的方式创建数据卷的时候,我们每次在运行镜像的时候都需要去指定宿主机目录和容器目录,不便于维护与迁移,给大家举个例子:例如我们的日志文件是存放在容器中的 /cloud-project/logs目录下,而且在项目的配置文件中也是指定到该目录下,对应到我们的宿主机是/mycloud-project/logs目录,如果说由于项目发布启动的时候,运维人员写错了目录名,那将是很大的问题。所以我们在生成镜像文件的时候就指定数据卷的目录岂不是更好。

  具体操作是,我们根据Dockerfile目录中通过VOLUMN指定数据卷的位置,至于什么是Dockerfile,在后面的篇章中会讲解。

A. 新建一个空的目录:mkdir my-dockerfile

B. 新建Dockerfile文件

C.在Dockerfile中添加如下内容:

FROM centos

VOLUMN ["/containerDataVolumn"]

CMD /bin/bash

D.执行命令 docker build -t mycentos:me .  生成名为mycentos,tag为me的新的镜像文件。注意:最后的一个点不能省略,它不是结束的句号(我在这里栽了很大的跟头)!!!

E. 根据mycentos:me这个镜像启动一个容器,观察根目录下会生成 containerDataVolumn文件夹,如下图所示:

F. 那么如何查看,容器中的数据卷目录对应的宿主机的目录呢?上一小节我们讲过,可以通过 docker inspect 容器ID 命令查看,结果如下图所示: 

补充:mysql的数据卷的启动方式,如下:

docker run --name myMysql -e MYSQL_ROOT_PASSWORD=7890 -v /mydatas/mysql/datas:/var/lib/mysql -p 3307:3306 -d mysql:5.7.27

二. 容器数据卷(了解)

我们在上一节讲到使用数据卷实现容器数据的持久化,那么如何实现容器间数据的共享了?我们需要使用容器数据卷。其实就是利用数据卷的原理,将多个容器中的目录映射到宿主机的同一个目录,其实他们就是同一份文件。在一个容器中对数据的改变在其他容器中都是可以感知到的,原因说白了,每个容器中看到的其实就是同一份文件,我们可以通过:stat 文件名 查看文件的inode信息,发现inode的编号都一样。

A. 通过  docker run -it -v /host-datas:/container-datas --name u1 ubuntu:18.04  命令启动一个容器。

B. 通过  docker run -it  --volumes-from u1 --name u2 ubuntu:18.04 命令启动另外一个容器

C. 在u1容器中的 /container-datas 目录下创建abc.txt文件,然后在u2容器中/container-datas目录下可以看到该文件。同理在u2容器中创建一个文件,在u1容器中也能看到该文件。

三. Dockerfile

2.1 Dockerfile是什么

Dockerfile是docker中镜像文件的的描述文件,说的直白点就是镜像文件到底是由什么东西一步步构成的。例如我们在淘宝上买了一件商品,但是这个商品需要组装才能使用,于是卖家就给了你一张图纸,你就按照图纸一步一步的组装起来,然后就成了你所需要的样子。那么Dockerfile就是这张图纸,镜像文件就是你需要的商品。Dockerfile名字可以随便命名,但是不建议你这做,还是按照规范来使用,首字母要大写。下面给出我们前几个章节使用到的ubuntu为例,来看看它的Dockerfile是怎么样的,如下图所示:

2.2 Dockerfile、镜像、容器

Dockerfile:是镜像的构建文件,描述的镜像是一步步怎么来的。

  镜像:是通过Dockerfile做出来的,包含操作系统基础文件和软件运行环境,它使用分层的存储方式。

  容器:是运行起来的镜像,简单理解,Docker镜像相当于程序,容器相当于进程。

2.3 Dockerfile的基本语法及执行流程

2.3.1 Dockerfile的基本语法

a.每个保留字必须放在每一行的开头,可以大写也可以小写,但是建议大写;

  b.指令按照顺序,从上往下依次执行;

  c.#表示注释;

  d.每条执行指令都会创建一个新的镜像,并且执行提交。

2.3.2 Dockerfile的执行流程

a.docker从基础镜像中执行一个容器;

   b.执行一条指令对容器进行修改;

   c.执行docker commit命令,提交新的镜像;

   d.在基于刚刚提交的镜像运行一个新的容器;

   e.执行Dockerfile中的下一条指令,按照b、c、d依次循环下去,直到所有的指令执行完毕。

2.3.3 演示讲解

FROM centos                          #指定要生成的镜像的基础镜像,开头第一句话必须也只能是FROM

MAINTAINER  qf@163.com               #指定作者是谁

RUN apt-get install -y vim           #执行 yum install -y vim 命令,安装vim

RUN apt-get install -y net-tools     #执行 yum install -y net-tools, 安装net-tools工具

WORKDIR /dev/                        #启动容器后,如果启动交互模式,直接进入到哪个目录

CMD ["/bin/bash"]                    #启动容器的时候,进入到/bin/bash这种命令行

如上代码所示,FROM、MAINTAINER、RUN、WORKDIR、CMD均为关键字,按照标准的规范需要大写;FROM centos表示基础镜像是centos,然后会启动centos这个容器,执行第二行代码又会生成新的镜像文件,然后提交,周而复始。

2.4 Dockerfile关键字

关键字                                  作用

FROM                            指定基础镜像

MAINTAINER                    作者的信息

RUN                                执行什么命令

EXPOSE                    容器对外暴露的端口

WORKDIR            进入到容器后进入到哪个目录

ENV                                配置环境变量

ADD                            将文件拷贝到镜像中并解压

COPY                            将文件拷贝到镜像中

VOLUME                                配置数据卷

CMD                                容器启动时候执行的命令

ENTRYPOINT                容器启动时候执行的命令

A.ADD指令,现在定义这样一个Dockerfile,代码如下所示:

FROM ubuntu:18.04

MAINTAINER  qf@163.com

RUN mkdir /datas

ADD jdk-8u60-linux-x64.tar.gz /datas/

WORKDIR /datas/

CMD ["/bin/bash"]

首先必须将jdk-8u60-linux-x64.tar.gz文件拷贝到Dockerfile同级目录下,如下图所示:

执行命令:docker build -t myubuntu .  构建myubuntu镜像,如下图所示:

然后启动容器,进入到 /datas/目录下,会发现 jdk1.8.0_60 目录,表示add命令还执行了解压命令,如下图所示:

B.COPY命令,先定义一个Dockerfile, 代码如下:

FROM centos

MAINTAINER  qf@163.com

RUN mkdir /datas

COPY jdk-8u60-linux-x64.tar.gz /datas/

WORKDIR /datas/

CMD ["/bin/bash"]

执行命令:docker build -t myubuntu .  构建myubuntu镜像。

然后启动容器,进入到 /datas/目录下,会看到jdk-8u60-linux-x64.tar.gz文件,并没有解压,如下图所示:

C.ENV命令,配置环境变量,还是用上面提到的jdk为例,做过Java开发的朋友都知道,jdk需要配置环境变量,Dockerfile的内容如下所示:

FROM ubuntu                      

MAINTAINER qf@163.com  

RUN mkdir -p /datas/

ADD jdk-8u60-linux-x64.tar.gz /datas/

ENV JAVA_HOME=/datas/jdk1.8.0_60                    #配置JAVA_HOME

ENV PATH=$JAVA_HOME/bin:$PATH                       #配置PATH

CMD ["/bin/bash"]

容器启动后,输入:java  -version命令,就能看到我们熟悉的内容了。

D.CMD关键字,在镜像构建阶段不执行,在容器启动阶段执行(而的RUN关键字定义的指令在容器构建阶段就会执行,请记住它与CMD的区别)。如果一个Dockerfile中有多个CMD命令,后面的会覆盖前面的,说白了只有最后一个生效,如下代码和注释:

............省略............

CMD echo "<<<<<<<<<<<nice to meet you>>>>>>>>>>"

CMD /bin/bash

CMD echo "==========How are you?============="    #当容器启动的时候只有该行代码会执行,会将前两行代码覆盖

CMD还有一个问题,就是当我们使用 docker run命令的时候,我们可以在整个docker命令的最后加上其他额外的命令,那么额外的命令会覆盖Dockerfile中所有的CMD命令,例如我们执行如下命令:docker run -it centos ls / -l,最终的结果如下图所示: 

E. ENTRYPOINT指令,和CMD命令差不多,如果一个Dockerfile中有多个ENTRYPOINT,只有最后一个生效。但是他们还是有区别的,如果ENTRYPOINT后面有CMD,当以exec的方式运行的时候,CMD的值会作为参数给ENTRYPOINT,可能很多人看到这句话不大理解,那么我们来两个例子:

例一:

FROM centos                      

MAINTAINER  zhengjingmao@163.com  

RUN mkdir -p /datas/

ENTRYPOINT ["echo", "hello"]

CMD ["world"]              #会将world作为echo hello的参数,最后的命令其实为echo hello world

例二:

FROM centos                     

MAINTAINER  zhengjingmao@163.com 

RUN mkdir -p /datas/

ENTRYPOINT ["echo", "hello"]

总结:当我们理解了CMD和ENTRYPOINT两个命令的区别后,以后在使用的过程中就不会出现各种问题了。

四. docker-compose

在开发一个应用的时候,我们需要其他的很多东西,例如数据库,nginx,网站应用等很多的环境,而docker又推崇的是每一个容器只运行一个进程,那么我们势必得很多的容器,那么我们得通过docker build命令一个个的构建镜像,然后在通过docker run命令启动一个个容器,那么当我们修改了应用后,我们又得去重复上面的操作。而且容器与容器之间存在着很多的依赖,我们在操作的时候还得去考虑先启动哪个容器,在启动另外一个容器,这些操作和步骤都得花上大量的精力。那么docker-compose的出现就是为了解决这个问题。

docker-compose是一种容器编排技术,我们可以编写一个docker-compose.yml文件,在文件中编排好我们的服务,只用通过一个命令即可搞定所有的工作。

3.1 安装docker-compose

A. 运行如下命令获取最新版的docker-compose

curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

B. 给二进制文件加上执行权限

chmod +x /usr/local/bin/docker-compose

如果docker-compose命令无效,可以给这个文件创建一个在 /usr/bin 目录下的一个软连接,如下所示:

ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

C. 验证docker-compose是否安装成功

docker-compose --version

3.2 docker-compose.yml的编写

version: "3.7"

services:

  mysql:

    image: mysql:5.7.26

    ports:

      - "3306:3306"

    environment:

      - MYSQL_ROOT_PASSWORD=miller

    network_mode: "host"

    volumes:

      - "/datas/db:/var/lib/mysql"

      - "/docker-compose/mysql/my.cnf:/etc/my.cnf"

  eureka-server:

    build:

      context: ./eureka-server

      dockerfile: Dockerfile

    ports:

      - "8761:8761"

    network_mode: "host"

  provider:

    build:

      context: ./provider

      dockerfile: Dockerfile

    ports:

      - "6666:6666"

    network_mode: "host"

    depends_on:

      - "mysql"

    command: ["./wait-for-it.sh", "mysql:3306", "--", "java", "-jar", "provider.jar"]

  consumer:

    container_name: consumer

    build:

      context: ./consumer

    network_mode: "host"

    ports:

      - "8080:8080"

version

指定docker-compose文件的版本,对应的版本信息如下:

services

定义服务。

image

指定基础镜像。

ports

指定对外开放的端口。

environment

配置环境变量。

network_mode

网络模式,默认为bridge(桥接)模式。

volumes

指定数据卷。

context

要构建的镜像的上下文,说白了就是相对于docker-compose.yml文件的位置。

dockerfile

指定Dockerfile文件的名字,如果名字为Dockerfile的话,不用指定。

depends_on

指定容器所依赖的另外一个容器的服务名,但是并不会等待所依赖的容器启动才去启动这个容器。

3.3 启动

docker-compose up: 如果没有构建过镜像,首先会构建镜像,然后启动容器。

docker-compose up --build: 无论镜像是否存在,首先会构建镜像,然后启动容器。

docker-compose start [service...]: 启动已经存在的容器。

3.4 wait-for-it.sh使用

地址:https://github.com/vishnubob/wait-for-it

./wait-for-it.sh www.google.com:80 -- echo "google is up"

如果连接上谷歌的服务器,输出“google is up”

五. Docker的工程化实践

A. 创建spring-boot的工程。

在主类上加上@SpringBootApplication, 来标注该类为一个Spring-boot项目的启动类。

B.  编写代码。

C. 将spring-boot项目打包后的jar包上传到ubuntu的/spring-boot/目录下。

D. 执行:docker run -it -v /spring-boot:/jarDir -p 8088:8080 mcr.microsoft.com/java/jre:8u192-zulu-alpine  /bin/sh -c "java -jar /jarDir/spring-boot-1.0-SNAPSHOT.jar" 启动我们的docker的jre容器,然后运行我们java程序。

E. docker run -it -e MYSQL_ROOT_PASSWORD=123456 -p 3305:3306 mysql:5.7.26,启动mysql的容器。

F.  将mysql容器的数据通过数据卷的方式映射到宿主的目录下。

六. Idea与docker的整合

6.1 安装docker插件

6.2 配置docker的端口

修改/lib/systemd/system/docker.service文件,将14行代码改为:

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

6.3 插件设置

6.4 Dockerfile

将Dockerfile文件放在项目的根目录下,文件内容如下:

FROM store/oracle/serverjre:8

MAINTAINER decent_cat@126.com

ADD /target/boot-1.0-SNAPSHOT.jar boot.jar

EXPOSE 8080

CMD ["java", "-jar", "boot.jar"]

6.5 运行配置

七. Docker私有仓库的搭建

A. 拉取registry仓库

docker pull registry:2

B. 启动容器

docker run -d -p 5000:5000 --restart always --name registry registry:2

C. 在浏览器访问:http://192.168.223.141:5000/v2/,会出现如下内容,表示registry启动成功

D.更改 /etc/hosts 文件,在文件的末尾加入上下代码,其中192.168.223.141 是本机IP

192.168.223.141  my-registry.com

E. 在 /etc/docker/daemon.json 文件中加入如下内容:

"insecure-registries": ["my-registry.com:5000"]

代码的完整内容如下:

F. 重启docker服务,命令如下:

systemctl daemon-reload

systemctl restart docker

G. 推送自己的镜像到docker私有仓库中:

# 将我们要推送到私有仓库的centos镜像打一个标签,名字叫my-centos, 这是my-centos就与本地的centos关联#  上了

docker tag centos my-registry.com:5000/my-centos

# 将之前已经关联的的镜像推送到私有镜像仓库

docker push my-registry.com:5000/my-centos

H. 查看镜像的命令

http://192.168.223.128:5000/v2/image_name/tags/list    #查看某个镜像的所有的tag

附录:


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335