基本概念
容器
什么是容器?Docker官方介绍:
将软件打包到标准化单元中,以进行开发,运输和部署。
容器是一个标准的软件单元,它将代码及其所有依赖打包,以便应用程序从一个计算环境快速可靠地运行到另一个计算环境。 Docker容器镜像是一个轻量级,独立的可执行软件包,包含运行应用程序所需的一切:代码,运行时,系统工具,系统库和设置。
容器镜像在运行时成为容器,对于Docker容器,镜像在Docker Engine上运行时成为容器。 适用于基于Linux和Windows的应用程序,无论基础架构如何,容器化软件运行结果始终相同。 容器将软件与环境隔离开来,并确保它可以统一工作,尽管开发和演示之间存在差异。
在Docker Engine上运行的Docker容器:
标准: Docker创建了容器的行业标准,因此它们可以在任何地方移植
轻巧:容器共享计算机的OS系统内核,因此不需要每个应用程序都具有OS,从而提高了服务器效率,并降低了服务器和许可成本
安全:应用程序在容器中更安全,并且Docker提供了业界最强大的默认隔离功能
虚拟化和容器化的区别
- 虚拟化是物理资源层面的隔离,容器是进程层面的隔离
- 容器在操作系统上运行,并与其他容器共享主机的内核。没有臃肿的操作系统,相对VM节省了大量资源开销。
容器化技术比虚拟机更灵活,更轻量小巧。
容器化解决的问题
- 标准化的迁移方式
- 提升部署效率,屏蔽环境带来的差异
- 统一的参数配置
- 降低开发与运维之间的沟通桥梁
Docker
- Docker是一个提供应用打包,部署与运行应用的容器化平台
- 开源的应用容器引擎,使用
Go
语言开发,基于Linux内核 的cgroup
,namespace
以及使用Union FS
技术来实现资源控制、工作区隔离、操作系统虚拟化 - Build once,Run anywhere,Configure once,Run anything
Docker Engine
Docker Engine也就是Docker,Docker Engine为C/S模型,用户可以通过docker client向docker daemon发送操作请求。
Docker Engine包括以下几部分:
- Docker Daemon是一个守护进程,属于C/S中的server
- REST API, docker daemon向外暴露的REST 接口
- Docker向外暴露的命令行接口(Command Line API)
因此我们可以通过Docker REST API
或者使用CLI
命令与Docker Daemon
进行交互。
Docker Daemon
负责创建和管理Docker 对象,例如镜像,容器,网络和卷。
镜像和容器
- 镜像是文件,是只读的,提供了运行程序完整的软硬件资源,是应用程序的"集装箱"
- 容器是镜像的实例,由Docker负责创建,容器之间彼此隔离
交互流程
常用命令
-
docker build
- 使用Dockerfile创建镜像 -
docker pull
镜像名<:tags> - 从远程仓库抽取镜像 -
docker images
- 查看本地镜像 -
docker run
镜像名<:tags> - 创建容器,启动应用 -
docker start
容器id - 启动容器 -
docker ps
- 查看正在运行中的镜像 -
docker rm
<-f> 容器id - 删除容器 -
docker rmi
<-f> 镜像名:<tags> - 删除镜像 -
docker exec
进入容器,可以在容器的Shell执行命令
示例
# 1.拉取远程镜像
# docker pull tomcat
# 2.运行tomcat
# docker run tomcat
......省略一堆日志
11-Sep-2020 03:39:47.314 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
11-Sep-2020 03:39:47.323 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [64] milliseconds
tomcat是启动成功了,但是我们的界面也进入了tomcat的启动界面,想要进行下步操作只能另外启动一个shell了,不太方便。Ctrl + c中断,这时可以使用docker run中的参数d
(相关参数可以通过docker run --help
查看)
-d: 后台运行容器,并返回容器ID
# docker run -d tomcat
e8131c2c78e12bda89db059ee184b4fe9afc2a47217631c96a9947da823e6c07
# 查看运行的容器
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8131c2c78e1 tomcat "catalina.sh run" 30 seconds ago Up 29 seconds 8080/tcp objective_franklin
Docker宿主机与容器通信
此时如果要通过外部访问是访问不通的,原因是容器暴露的端口并未与宿主机映射。
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
# 先停止上面启动的容器(`e8131c2c78e1`为上面创建的容器id,通过docker ps可以查看运行的容器以及相关的参数)
# docker stop e8131c2c78e1
# docker run -d -p 8080:8080 tomcat
90c7a49e7495fd2dd418cfc36b5678b34d617618cf9089bfa4d99d4f5e79c937
容器内部结构
容器内部依赖关系如下:
如果我们要在tomcat中添加一个html,可以直接使用docker exec
命令进入容器内部。
docker exec -it [容器id] /bin/bash
# docker exec -it 90c7a49e7495 /bin/bash
# 默认进入到tomcat的工作目录
root@90c7a49e7495:/usr/local/tomcat# cd webapps
root@90c7a49e7495:/usr/local/tomcat/webapps# mkdir ROOT && echo "Hello World" > ROOT/index.html
# Ctrl + d 回到宿主机访问tomcat服务查看结果
# curl localhost:8080
Hello World
挂载本地目录
如果每次都需要进入容器修改或者新增文件那也太麻烦了,此时我们可以将本地目录挂载到容器里。
--volume , -v: 绑定一个卷
# 在宿主机创建一个目录
# mkdir /webapps
# 停止上面启动的容器
# docker stop 90c7a49e7495
# 启动,加上-v参数挂载目录
# docker run -d -p 8080:8080 -v /webapps:/usr/local/tomcat/webapps tomcat
51d3b61731d12025c3a9d40f78bd9e1b568dfd1b1392c4cee74cacd78ff2c0bd
# cd /webapps
# mkdir ROOT && cd ./ROOT && echo "hello world" > index.html
# curl localhost:8080
hello world
容器的生命周期
DockerFile
Dockerfile
是一个用来构建镜像的文本文件,其中包含镜像构建的指令。
构建镜像命令:
docker build -t 机构/镜像名<:tags> Dockerfile目录
一张来自互联网的图,使用幽默诙谐的语言对相关指令的解释:
示例
本次示例为构建一个tomcat应用镜像,直接将html文件
放置到webapps
目录,如果是java
应用直接将war包放置到该目录即可。
# ls
Dockerfile index.html
DockerFile
文件内容:
FROM tomcat:latest
WORKDIR /usr/local/tomcat/webapps/ROOT/
COPY index.html .
html
文件内容:
<h1>hello world</h1>
执行构建镜像
# docker build -t hosjoy/mytomcat:1.0 .
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM tomcat:latest
---> d5eef28cf41d
Step 2/3 : WORKDIR /usr/local/tomcat/webapps/ROOT/
---> Running in 3d945ec4369e
Removing intermediate container 3d945ec4369e
---> 3d823064c72f
Step 3/3 : COPY index.html .
---> 3f10023cfd3e
Successfully built 3f10023cfd3e
Successfully tagged hosjoy/mytomcat:1.0
运行容器
# docker run --rm -d -p 8080:8080 hosjoy/mytomcat:1.0
92050690ca846241c1944962c24ec2a2eb6ae060cb944bcaa69987a0a09bcc5f
# curl localhost:8080
<h1>hello world</h1>
镜像分层
Docker镜像里面是一层层的文件系统,基于Union FS
(联合文件系统)技术,可以将多层目录挂载到一起,形成一个虚拟文件系统,虚拟文件系统的目录结构就像普通 Linux 的目录结构一样,Docker通过这些文件再加上宿主机的内核提供了一个Linux 的虚拟环境。
Linux文件系统由bootfs
和 rootfs
两部分组成:
-
bootfs
(boot file system):主要包含bootloader
和kernel
,Linux启动时会加载bootfs
文件系统,boot将内核加载到内存中后,此时系统会卸载bootfs
。 -
rootfs
(root file system): 包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc
等标准目录和文件,不同的Linux 发行版(如ubuntu
和CentOS
)在rootfs
这一层会有所区别。
当运行镜像时,Docker会生成一个新的可写层并加载到镜像的顶层。这一层通常称为"容器层",之下都是"镜像层",最底层的为基础镜像(base image)。
容器层可以读写,镜像层只允许读取。
分层带来的好处:
- 共享资源,例如:有多个镜像都从相同的base镜像进行构建,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份base镜像,就可以为所有的容器服务了。而且镜像的每一层都可以被共享。
- 可以并发上传下载,提升构建速度。如果修改了镜像,相当于在原有镜像基础再加一层,推送到仓库也不需要全部推送,只需要推送新加的一层即可。