Docker是一个开源的容器引擎,它有助于更快的交付应用。Docker可将应用程序和基础设施层隔离,并且能将基础设施当做程序一样进行管理。使用Docker可更快地打包、测试以及部署应用程序,并可以缩短从编码到部署运行代码的周期
MacOS下载docker地址:https://docs.docker.com/desktop/mac/install/
一、Docker三要素
- 镜像(image):镜像就相当于一个只读的模板。镜像可以用来创建docker容器,一个镜像可以创建很多容器。
镜像与容器的关系类似与Java中的类与对象的关系。
//User类就相当于镜像,u1、u2、u3三个不同的实例就相当于容器,不过这三个都是基于User创建出来的
User u1 = new User();
User u2 = new User();
User u3 = new User();
- 容器(Container):容器使用镜像创建的运行实例。他可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。容器可以看作是简易版的Linux运行环境(包括用户空间、进程空间、网络空间等)和运行在其中的应用程序。
- 仓库(Repository):仓库就是集中存放镜像文件的地方,我们可以把制作好的镜像发布到仓库中,需要的时候拉下来即可。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是Docker Hub。存放了很多镜像供用户下载。国内的公开仓库包括阿里云、网易云等等。
docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过这个镜像文件才能生成Docker容器。image文件可以看作是容器的模板。Docker根据image文件生成容器的实例同一个image文件。同一个image文件,可以生成多个同时运行的容器实例。
一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是容器。
二、镜像加速器配置
默认情况下docker拉取镜像是从DockerHub上拉取镜像,国外的网站速度很慢。所以需要配置一个国内的仓库,后续拉取的时候直接从国内仓库拉取。
- 网易云加速器:https://hub-mirror.c.163.com
- 百度云加速器:https://mirror.baidubce.com
对于使用 macOS 的用户,在任务栏点击 Docker Desktop 应用图标 -> Perferences,在左侧导航菜单选择 Docker Engine,在右侧像下边一样编辑 json 文件。修改完成之后,点击 Apply & Restart 按钮,Docker 就会重启并应用配置的镜像地址了。(当然也可以直接去**~/.docker/daemon.json**文件中配置)
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动。配置完成后需要重启docker。
检查加速器是否生效:
执行docker info命令,如果从结果中看到了如下内容,说明配置成功。
Registry Mirrors:
https://hub-mirror.c.163.com/
三、docker命令
1.帮助命令
- docker version
- docker info (docker信息的描述)
- docker help (重要,docker命令使用的帮助文档)
2.镜像命令
docker images 列出本机上所有的镜像(加上-q表示只获取镜像ID)
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
同一个仓库源可以有不同的标签,代表这个仓库源的不同版本,我们使用REPOSITORY:TAG来定义不同的镜像。如不指定标签,则默认为latest。
docker search 镜像名字:用于从镜像仓库查询某个镜像。
docker pull 镜像名字:TAG :从镜像仓库拉取镜像,不写TAG默认为latest。
docekr rmi 镜像名字:Tag :删除某个镜像。(加上-f表示强制删除)
删除多个镜像:docker rmi 镜像名字1:Tag 镜像名字2:Tag
删除全部:docker rmi -f $(docker images -q)
3.容器命令
docker run [options] image [command][arg……] 根据指定镜像创建容器实例并运行
options说明:
- -d:后台运行容器,并返回容器ID
- -P:随机端口映射
- -p:指定端口映射(可以这样指定 hostPort:containerPort,注意这里的hostPort指的是docker对外暴露的服务端口,containerPort才是docker内部应用真正监听的端口)
- -i:以交互模式运行容器,通常与-t结合使用
- -t:为容器分配一个伪终端,通常与-i结合使用。
- –name “容器新名字”:为容器指定一个新名字。
- -e -e username=“XXX”: 设置环境变量。
示例1:拉取docker拉取centos并后台运行。
通过上面的方式在docker容器内运行centos,我们可以docker客户端查看,但是会发现容器并不是运行状态。
这个是因为:Docker容器后台运行,就必须有一个前台进程。如果运行的命令不会让程序一直挂起,那么就会自动退出(自杀)。
示例2:以️交互式运行的方运行centos
这种方式会为容器分配一个伪终端(如上我们进入了容器中运行的centos的终端[root@9feb4df70129]),相当于通过宿主机进入到容器的终端,由于前台进程一直存在所以容器一直运行着如图。
可以通过exit退出伪终端回到宿主机,这种方式会导致容器关闭。也可以通过 control + P + Q可以退出(离开)容器。(这种方式不会关闭容器)
示例3:通过后台运行的方式运行一个SpringBoot应用
由于我已经制作好了SpringBoot应用的镜像,所以直接运行即可,执行命令
dokcer run -d -p hostPort:containerPort --name "容器新名字" 镜像名字或镜像ID
这里我执行的是dokcer run -d -p 8888:8080 80b620c5509d
查看docker客户端,可以看到后台运行SpringBoot应用容器并没有关闭。
这是因为SpringBoot应用一直在默默运行,所以容器不会自杀。
特别的: 这里需要通过 http://localhost:8888/test 去访问SpringBoot应用。SpringBoot应用的端口号是8080,但是我们却通过8888去访问,这是因为我们访问的是docker提供的服务,docker对外暴露的端口是8888,当我们访问8888的时候docker会映射到自身端口号为8080的应用。
docker ps:列出当前所有正在运行的容器
- 加上-l可以返回上次运行过的容器信息。
- -n 数字 表示历史运行过的几条容器信息。
docker start 容器ID或者容器名:启动容器
docker restart 容器ID或者容器名:重启容器
docker stop 容器ID或者容器名:停止容器
docker kill 容器ID或者容器名:强制停止容器
docker logs -t --tail 10 容器ID或者容器名:查看容器的日志信息(-t的作用是显示日志打印时间,–tail 是制定显示末尾多少行)
docker top 容器ID或者容器名:查看容器内运行的进程
docker rm 容器ID或者容器名:删除容器
dokcer exec -it 容器ID 想要执行的命令:这个相当于让容器自己执行一下指定的命令并将结果返回给你。
如下是之前运行的一个SpringBoot应用,现在想进入容器终端交互运行
docker attach 容器ID:这个会进入容器终端。
docker cp 容器ID:容器内路径 宿主机路径:从容器内拷贝文件到目标主机。
docker inspect 容器ID:查看容器的详细信息
四、镜像的分层结构
我们pull一个镜像的时候通常会看到还有其他附带的东西被拉取下来,比如如下只pull了一个SpringBoot应用,但是显示667M。这是源于docker镜像的分层结构,一个SpringBoot应用在容器上运行需要操作系统内核,JDK8,SpringBoot的应用程序等。这些就是这个镜像的每一层,采取分层结构最大的好处就是共享资源,每个镜像的每一层都可以被共享。也就是说以后获取的其他镜像如果也需要JDK8,那么不需要重复拉取,因为宿主机上已经存在了,且可以共享。
五、Dockerfile
Dockerfile是用来构建docker镜像的构建文件,是由一系列命令和参数构成的脚本。Docker通过读取Dockerfile中的指令自动生成镜像。
1.Dockerfile构建过程解析
- 每条指令都必须为大写字母且后面要跟随至少一个参数。
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
2.Dockerfile主要指令说明
- FROM:当前所创建镜像的基础镜像
- MAINTAINER:指定维护者信息(作者信息)
- RUN:容器构建时需要运行的命令
- ENV:声明环境变量(后续指令中还可以引用这个变量)
- ADD:将宿主机的路径下的内容添加(复制)到容器中的路径下,可以为URL;如果为tar文件,会自动解压到路径下
- ENTRYPOINT:指定一个容器启动时要执行的命令(用法:ENTRYPOINT [“executable”, “param1”, “param2”])
- EXPOSE:声明镜像内服务所监听的端口
- VOLUME:指定容器数据卷(数据卷就是容器数据持久化的地方)
示例1:基于centos镜像制作一个新的centos镜像(添加vim功能)
由于远程仓库获取的centos不支持vim,所以这里构建一个支持vim的centos镜像,Dockerfile文件如下:
FROM centos:latest
ENV AUTHOR yhj
WORKDIR /root
MAINTAINER $AUTHOR
RUN yum -y install vim
EXPOSE 80
ENTRYPOINT ["/bin/bash"]
执行如下命令:
//-f 指定Dockerfile路径,-t指定创建镜像的名字与TAG
docker build -f ./Dockerfile -t mycentos:1.0 .
示例2:制作一个SpringBoot应用镜像
先把写好的SpringBoot应用打成可执行jar包,注意SpringBoot打包需要引入打包插件。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Dockerfile如下:
FROM java:8
EXPOSE 8080
ADD ./MySpringBoot.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
如上curl访问成功,说明应用启动成功。
六、数据卷VOLUME
docker将应用与运行环境打包形成容器运行,数据伴随着容器,但是我们对数据的要求是希望能够持久化。容器和宿主机之间希望有可能共享数据。而Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来。那么当容器删除后,数据自然也就没有了。为了能够使得数据保存下来,故有了容器数据卷。
卷的设计目的就是数据持久化,完全独立于容器的生存周期,因此docker不会在容器删除时删除其挂载的数据卷。(特别的,如果容器没有被删除,那么卷是不允许被删除的,只有容器被删除了,我们才可以删除其挂载的数据卷)
特点:
- 数据卷可以在容器中共享或重用数据
- 数据卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的声明周期一直持续到没有容器使用它为止
容器数据卷的添加
1. 直接命令添加
命令: docker run -v 宿主机路径:容器路径 镜像ID
//执行命令
docker run -it -v ~/myDataVolume:/containerDataVolume centos
docker inspect 容器ID 查看数据卷是否绑定成功,出现如图所示说明绑定成功。你还可以进入容器centos终端看到新建了一个/containerDataVolume目录。
共享数据验证:如下在主机~/myDataVolume目录下新建一个test.txt文件,再次启动容器查看/containerDataVolume目录下也产生了一个test.txt文件。随后在容器中操作删除后宿主机上的文件也被删除了。
2.Dockerfile添加
在Dockerfile中使用VOLUME[“容器目录1”,“容器目录2”] 指令来给镜像添加一个或多个数据卷。
FROM java:8
EXPOSE 8080
VOLUME ["/tmp"]
……
查看容器中的共享目录如下:
这与docker客户端中显示的数据一致
通过Dockerfile这种方式无法指定宿主机的目录,docker会帮我们生成一个匿名目录“Source”。通过docker inspect 容器ID 命令查看如下:
mac中没有找到“Source”指定的宿主机目录,不过inspect有显示。
七、docker安装mysql
1.拉取mysql镜像(由于镜像仓库中已经有mysql镜像,所以拿来即用即可)
2.启动docker容器运行mysql
//如下指定了几个-v项,只是为了方便直接从宿主机上操作查看容器上安装的mysql配置等数据
//MYSQL_ROOT_PASSWORD=123456:设置环境变量MySQL服务root用户的密码。
docker run -p 54199:3306 --name mysqlContainer
-v ~/myDataVolume/mysql/conf:/etc/mysql/conf.d
-v ~/myDataVolume/mysql/logs:/logs -v ~/myDataVolume/mysql/data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456
-d mysql:5.6
如上我们开启交互运行,登入了容器中的mysql,成功创建了库表。
查看共享数据绑定也是成功的
宿主机登陆操作docker中的mysql
部署好mysql服务后需要让外部能够操作,这里尝试用宿主机操作容器内的mysql。首先需要进到容器中,为mysql添加远程连接权限,并重启。执行如下命令:
//mysql为用户授权。表示任何ip的主机都可以通过root账户登陆
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
//刷新
FLUSH PRIVILEGES;
//重启mysql服务
service mysql restart
完成之后退回宿主机登陆mysql。
注意由于docker对外暴漏的端口是54199,所以指定的端口是54199,主机使用回环地址127.0.0.1,因为docker进程本身也是在本机上运行的。
docker学习地址:
https://www.runoob.com/docker/docker-architecture.htmlhttps://yeasy.gitbook.io/docker_practice/install/mirror