一、核心概念
镜像概念
类似与虚拟镜像,可以理解为一个只读模板,一个独立的文件系统。例如一个镜像可以包含基本的操作系统环境。
容器概念
类似于一个轻量级沙箱,Docker容器来运行和隔离应用。容器是从镜像创建的应用实例。
即,Docker利用容器来运行应用,而Docker容器是又Docker镜像创建的实例。
仓库概念
类似与代码仓库,是Docker集中存放镜像的场所。
二、安装配置
Linux安装
命令安装
1、卸载旧版
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2、添加软件源,以及支持devicemapper存储类型
$ sudo yum update
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
3、添加yum软件源
$ yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo \
4、安装docker
yum install docker-ce docker-ce-cli containerd.io
5、更新yum软件源
$ sudo yum update
$ sudo yum install -y docker-ce
6、启动docker
$ sudo systemct start docker
脚本安装
$ curl -fsSL https://get.docker.com/ | sh
or
$ wget -qO- https://get.docker.com/ | sh
Win10安装
下载地址
https://download.docker.com/win/stable/Docker%20Desktop%20Installer.exe
企业版
需要开启虚拟机:控制面板->程序->启用或关闭Windows功能->Hyper-V
家庭版
无虚拟机选项,需执行以下脚本开启Hyper-V选项
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
或者CMD执行以下命令伪装成专业版
REG ADD "HKEY_LOCAL_MACHINE\software\Microsoft\Windows NT\CurrentVersion" /v EditionId /T REG_EXPAND_SZ /d Professional /F
开放端口
vim /usr/lib/systemd/system/docker.service
在ExecStart后面加上-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock \
然后执行重启
systemctl daemon-reload
systemctl restart docker
# 查看端口是否启动
# 全部端口状态
netstat -tunlp / ss 0tnl
# 查看2375端口状态
netstat -tunlp | grep 2375
三、镜像使用
设置阿里镜像
touch /etc/docker/daemon.json
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://xruvamby.mirror.aliyuncs.com"]
}
systemctl daemon-reload
systemctl restart docker
下载镜像
$ docker search image [:version]
$ docker pull image [:version]
查看镜像
$ docker images
options:
-a,--all:列出所有镜像
-f,--filter:过滤镜像
--digests:列出镜像的数字摘要值
添加标签
$ docker tar images:version myImage:version
删除镜像
$ docker rmi image [image...] / docker rmi imageid
options
-f, -force:强制删除镜像,即使又容器依赖她
-no-prune:不清理未带镜像标签的父镜像
# 删除所有镜像
$ docker rmi `docker images -q`
或
$ docker rmi $(docker images -q)
或
docker rmi $(docker images -q) -f
清理镜像
$ docker image prune
options:
-a,-all:删除所有无用镜像,不光是临时镜像
-filter:过滤清理镜像
-f,-force:强制删除镜像,不确认
创建镜像
- 基于已有容器创建
$ docker [container] commit
options:
-a,--author="":作者信息
-c,--chande=[]:提交的时候执行Dockerfile指令
-m,--message="":提交消息
-p,--pause=true:提交时暂停容器运行
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f7bb5701a33c 5 days ago 126MB
$ docker run -it nginx /bin/bash
$ touch example
$ exit
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
95f8c2992130 nginx "/bin/bash" 25 seconds ago Exited
$ docker commit -a 'example' -m 'example' 95f8c2992130 example:latest
sha256:1bc1d44dd77f2aebb6d060caff42d755155d6e4eae817a03185e8390a01b9613
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example latest 1bc1d44dd77f 30 seconds ago 126MB
nginx latest f7bb5701a33c 5 days ago 126MB
- 基本本地模板导入
$ docker import [options] file|url|-[repository[:tag]]
# 直接导入一个镜像,可使用OpenVZ提供的模板来创建
# OpenVZ模板下载地址:https://openvz.org/Download/templates/precreated
# 下载Ubuntu-18.04模板压缩包
$ cat ubuntu-18.04-x86_64-minimal.tar.gz | docker import - ubuntu18.04
镜像文件
- 存出镜像
$ docker save [-o,-output,string]
$ docker save -o nginx.tar.gz nginx:latest
- 载入镜像
$ docker load [-i,-input,-string]
$ docker load -i /usr/local/example/example.tar.gz
or
$ docker load < /usr/local/example/example.tar.gz
上传镜像
$ docker push
$ docker tag example:latest /user/example:latest
$ docker push user/example:latest
运行镜像
# 示例
docker run -d --name docker -p 8080:8080 -v /opt/logs/:/logs/ docker
四、容器使用
创建容器
- 新建容器
$ docker create -it nginx:latest
- 启动容器
$ docker start containerid
- 新建并启动容器
$ docker run -it container /bin/bash
$ docker run -it nginx:latest /bin/echo 'Hello World'
$ docker run -d -p 8080:8080 --name docker-service -v /opt/logs/:/logs/ docker-service
- 守护状态运行
$ docker run -d container
- 查看容器输出
$ docker logs
options
-details:打印详细信息
-f,-follow:持续保持输出
-since string:输出从某个时间开始的日志
-tail string:输出最近的若干日志
-t,timestamps:显示时间戳信息
-until string:输出某个时间之前的日志
停止容器
- 暂停容器
$ docker pause container_name
$ docker unpause container_name
- 终止容器
$ docker stop container
$ docker ps -qa
进入容器
- attach
$ docker attach container
options
--detach-keys[=[]]:指定退出attach模式的快捷键序列,默认是CTRL-p,CTRL-q
--no-stdin=true|false:是否关闭标准输入,默认是保持打开
--sig-proxy=true|false:是否代理收到的系统信号给应用进程,默认true
- exec
$ docker exec -it
options
-d,--detach:在容器中后台执行命令
--detach-keys="":指定将容器切回后台的按键
-e,--env=[]:指定环境变量列表
-i,--interactive=true|false:打开标准输入接受用户输入的命令,默认值是false
--privileged=true|false:是否给执行命令以最高权限,默认是false
-t,-tty=true|false:分配伪终端,默认值是false
-u,--user="":执行命令的用户名或id
$ docker exec -it container_id /bin/bash
删除容器
$ docker rm
options
-f,--force=false:是否强行终止并删除一个运行中的容器
-l,--link=false:删除容器的连接,但保留容器
-v,--volumes=false:删除容器挂载的数据卷
导入导出
- 导出容器:即导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态
$ docker export [-o|--output[=""]] container
$ docker export -o example.tar.gz container_id
- 导入容器
$ docker import [-c|--change[=[]] [-m|--message[=MESSAGE]] file|url-[REPOSTITORY[:TAG]]
$ docker import - test/example:latest
查看容器
- 查看容器详情
$ docker container inspect container_name
- 查看容器内进程
$ docker top container_name
- 查看统计信息
$ docker stats
options
-a,-all:输出所有容器的统计信息,默认仅在运行中
-format string:格式化输出信息
-no-stream:不持续输出,默认会自动更新持续实时结果
-no-trunc:不截断输出信息
其他命令
- 复制文件
$ docker cp
# 将本地的路径data复制到test容器的/tmp路径下
$ docker cp data test:/tmp/
- 查看变更
$ docker container diff container_name/id
$ docker container diff 8c07d38cdf7b
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /run
A /run/nginx.pid
C /usr
C /usr/local
A /usr/local/aegis
A /usr/local/aegis/aegis_client
A /usr/local/aegis/aegis_client/aegis_10_75
A /usr/local/aegis/aegis_client/aegis_10_75/data
A /usr/local/aegis/aegis_client/aegis_10_75/data/data.5
- 查看端口映射
$ docker container port container_name/id
五、数据管理
- 数据卷:容器内数据直接映射到本地主机环境
- 数据卷容器:使用特定的容器去维护数据卷
数据卷
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器。
- 创建数据卷
$ docker volumn create -d local folder
# 数据卷位置
$ ls -l /var/lib/docker/volumes
- 绑定数据卷
$ docker run -mount
-mount支持三种数据类型的数据卷
volume:普通数据卷,映射到主机/var/lib/docker/volumes
bind:绑定数据卷,映射到主机指定路径下
tmpfs:临时数据卷,只存在内存中
六、Dockerfile
普通Dockerfile
# 基础镜像
FROM openjdk:8
# 作者
MAINTAINER ohnahng@outlook.com
# VOLUME 指定了临时文件目录为/tmp。
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为app.jar
ADD docker-0.0.1-SNAPSHOT.jar app.jar
# 运行jar包
RUN bash -c 'touch /app.jar'
# 执行项目 app.jar。为了缩短 Tomcat 启动时间,添加一个系统属性指向 “/dev/./urandom”
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
或者
FROM openjdk:8
EXPOSE 8080
ARG JAR_FILE=target/*.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Spring Boot 2.3.0分层
Spring Boot 2.3.0中引入了两个新功能,以帮助改进这些现有技术:buildpack支持和分层jar,提高构建速度和效率。
Buildpack
Spring Boot 2.3.0直接支持Maven和Gradle的buildpack,可以将镜像快速获取到本地运行的Docker守护程序中。
- Maven:mvn spring-boot:build-image($ ./mvnw spring-boot:build-image)
- Gradle:gradle bootBuildImage
Layered Jar
影响Docker构建镜像速度和效率的因素:基础镜像大小、Dockerfile指令层数和Jar包大小。
分层 jar 的思想就是把Jar再根据规则细分,业务 class 和 三方 jar 分别对应镜像的不同层,这样改动业务代码,只需变动很少的内容 提高构建速度。
- Spring Boot Jar包结构
META-INF/
MANIFEST.MF
org/
springframework/
boot/
loader/
BOOT-INF/
classes/
lib/
分为三个主要部分:
classes是用于引导jar加载的类
Spring Boot应用程序类是在 BOOT-INF/classes
依赖是在 BOOT-INF/lib
如果分层,则结构为
├─BOOT-INF
│ ├─classes
│ │ └─com
│ │ └─sora
│ └─lib
├─META-INF
│ └─maven
│ └─com.sora
│ └─docker
└─org
└─springframework
└─boot
└─loader
├─archive
├─data
├─jar
├─jarmode
└─util
BOOT-INF
|
│ classpath.idx
│ layers.idx
│
├─classes
│ │ application.yml
│ │ logback-spring.xml
│ │
│ └─com
│ └─sora
│ DockerApplication.class
│
└─lib
现在lib和classes文件夹已拆分并分类为图层。还有一个新layers.idx文件,提供了添加图层的顺序。
dependencies (对于常规发布的依赖项)
snapshot-dependencies (对于快照依赖性)
resources (用于静态资源)
application (用于应用程序类和资源)
此分层旨在根据应用程序构建之间更改的可能性来分离代码。库代码不太可能在内部版本之间进行更改,因此将其放置在自己的层中,以允许工具重新使用缓存中的层。应用程序代码更可能在内部版本之间进行更改,因此将其隔离在单独的层中。
- 提取图层
开启分层
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
Dockerfile
# 指定基础镜像,这是分阶段构建的前期阶段
FROM openjdk:8 as builder
# 执行工作目录
WORKDIR application
# 配置参数
ARG JAR_FILE=target/*.jar
# 将编译构建得到的jar文件复制到镜像空间中
COPY ${JAR_FILE} application.jar
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果
RUN java -Djarmode=layertools -jar application.jar extract
# 正式构建镜像
FROM openjdk:8
WORKDIR application
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
- 构建镜像
docker build -t docker-service .
或者
docker build --build-arg JAR_FILE=./*.jar . -t docker:1.0
修改业务代码,再次构建
docker build --build-arg JAR_FILE=./*.jar . -t docker:2.0
七、远程连接
1、编辑配置文件
$ vim /usr/lib/systemd/system/docker.service
ExecStart
-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock \
2、重新启动
方式一、systemctl
# 守护进程重启
$ sudo systemctl daemon-reload
# 重启容器服务
$ sudo systemctl restart docker
# 停止容器服务
$ sudo systemctl stop docker
方式二、service
重启docker服务
$ sudo service docker restart
关闭docker
$ sudo service docker stop