This commit is contained in:
法然
2022-10-07 23:23:44 +08:00
parent dd11a44b1f
commit e359df4680
37 changed files with 1044 additions and 82 deletions

View File

@@ -3,7 +3,7 @@
* [菜鸟教程](https://www.runoob.com/docker/ubuntu-docker-install.html)
* [参考文献](http://c.biancheng.net/view/3118.html)
## 一、环境配置的难题
## 1 环境配置的难题
软件开发最大的麻烦事之一,就是环境配置。用户计算机的环境都不相同,你怎么知道自家的软件,能在那些机器跑起来?
用户必须保证两件事:操作系统的设置,各种库和组件的安装。只有它们都正确,软件才能运行。举例来说,安装一个 Python 应用,计算机必须有 Python 引擎,还必须有各种依赖,可能还要配置环境变量。
@@ -12,7 +12,12 @@
环境配置如此麻烦,换一台机器,就要重来一次,旷日费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。
## 二、虚拟机
虚拟化技术,**虚拟机和docker两种虚拟化技术**。
* 虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在系统上安装运行软件
* 容器,直接运行在宿主机的内核中,容器没有自己的内核,也没有虚拟硬件。轻便很多。
* 每个容器是相互隔离的,每个容器内都有一个属于自己的文件系统
## 2 虚拟机
虚拟机virtual machine就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统比如在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。
虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。
@@ -29,7 +34,7 @@
启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。
## 三、Linux 容器
## 3 Linux 容器
由于虚拟机存在这些缺点Linux 发展出了另一种虚拟化技术Linux 容器Linux Containers缩写为 LXC
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。
@@ -50,20 +55,114 @@ Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔
总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小得多。
## 四、Docker 是什么?
## 4 Docker 是什么?
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker就不用担心环境问题。
总体来说Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
## 五、Docker 的用途
### Docker为什么比VM快
* Docker有着比虚拟机更少的抽象层
* docker主要用的是宿主机的内核vm需要Guest OS
![](image/2022-10-07-21-25-06.png)
## 5 Docker 的用途
Docker 的主要用途,目前有三大类。
1提供一次性的环境。比如本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
1提供一次性的环境。比如本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。DevOps & CI/CD
2提供弹性的云服务。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
3组建微服务架构。通过多个容器一台机器可以跑多个服务因此在本机就可以模拟出微服务架构。
> * 传统开发jar运维部署。
> * 现在开发jar部署上线运维负责后续问题处理
## 6 Docker安装
### 通过脚本自动安装
```
curl -sSL https://get.daocloud.io/docker | sh
```
* 在centos上安装
```
# 卸载旧的版本
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装基本的安装包
$ sudo yum install -y yum-utils
# 不要用官网默认这个!
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认是国外的
# 换成下面的
$ sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里云镜像
更像软件包索引
yum makecache fast
安装docker引擎
yum install docker-ce docker-ce-cli containerd.io # docker-ce 社区版 ee 企业版
```
### 启动docker服务
```
sudo service docker start
sudo systemctl start docker
```
### 校验安装是否成功
查看版本
```
docker version
```
查看信息
```
docker info
```
### 运行docker镜像
运行hello-world容器
```
docker run hello-world
```
![](image/2022-10-07-21-16-32.png)
查看下载的镜像
docker images
![](image/2022-10-07-21-21-44.png)
### 加入用户组
```
sudo usermod -aG docker $USER
```
### 切换docker国内源
```
$ vi /etc/docker/daemon.json
{
"registry-mirrors":[ "https://registry.docker-cn.com" ]
}
$ systemctl restart docker
```

0
docker/10 Swarm.md Normal file
View File

0
docker/11 CICD.md Normal file
View File

59
docker/2 概念构成.md Normal file
View File

@@ -0,0 +1,59 @@
## 0 概述
### 构成原理
![](img/docker-structure.png)
* Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker SDK与 Docker 的守护进程通信。
* Docker 主机(Host)一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
* Docker Hub 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库Repository每个仓库可以包含多个标签Tag每个标签对应一个镜像。通常一个仓库会包含同一个软件不同版本的镜像而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
* Docker Machine。Docker Machine是一个简化Docker安装的命令行工具通过一个简单的命令行即可在相应的平台上安装Docker比如VirtualBox、 Digital Ocean、Microsoft Azure。
### 基本组成
![](image/2022-10-07-21-10-54.png)
- 镜像ImageDocker 镜像Image就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。 Docker 镜像(Images)Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
- 容器Container镜像Image和容器Container的关系就像是面向对象程序设计中的类和实例一样镜像是静态的定义容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。Docker 容器(Container)容器是独立运行的一个或一组应用,是镜像运行时的实体。
- 仓库Repository仓库可看成一个代码控制中心用来保存镜像。Docker 仓库RegistryDocker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。
- 公有仓库docker hub、
- 私有仓库
### 底层原理
* Docker是一个Client-Server结构的系统Docker的守护进程在主机上。通过Socket从客户端访问
* DockerServer接受到Docker-Client的指令
![](image/2022-10-07-21-24-11.png)
## 1 容器cantainer
### 容器较为官方的解释
一句话概括容器:容器就是将软件打包成标准化单元,以用于开发、交付和部署。
* 容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
* 容器化软件适用于基于 Linux 和 Windows 的应用,在任何环境中都能够始终如一地运行。
* 容器赋予了软件独立性,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。
* 虚拟化->容器技术LXC->cgroup&namespace
### 虚拟化技术
* 虚拟化技术是一种资源管理技术是将计算机的各种实体资源CPU、内存、磁盘空间、网络适配器等予以抽象、转换后呈现出来并可供分割、组合为一个或多个电脑配置环境。
* 由此,打破实体结构间的不可切割的障碍,使用户可以比原本的配置更好的方式来应用这些电脑硬件资源。这些资源的新虚拟部分是不受现有资源的架设方式,地域或物理配置所限制。一般所指的虚拟化资源包括计算能力和数据存储。
### LXC虚拟容器技术
Docker 技术是基于 LXCLinux container- Linux 容器)虚拟容器技术的。
* LXC其名称来自 Linux 软件容器Linux Containers的缩写一种操作系统层虚拟化Operating systemlevel virtualization技术为 Linux 内核容器功能的一个用户空间接口。
* 它将应用软件系统打包成一个软件容器Container内含应用软件本身的代码以及所需要的操作系统核心和库。通过统一的名字空间和共用 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。
* LXC 技术主要是借助 Linux 内核中提供的 CGroup 功能和 namespace 来实现的,通过 LXC 可以为软件提供一个独立的操作系统运行环境。
### cgroup 和 namespace
* namespace 是 Linux 内核用来隔离内核资源的方式。 通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。
* CGroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组 (process groups) 所使用的物力资源 (如 cpu memory i/o 等等) 的机制。

View File

@@ -1,43 +0,0 @@
# 安装与配置
## 1 通过脚本自动安装
```
curl -sSL https://get.daocloud.io/docker | sh
```
## 2 docker 命令
### version
查看版本
```
docker version
```
### info
查看信息
```
docker info
```
## 3 配置
### 加入用户组
```
sudo usermod -aG docker $USER
```
### 启动docker服务
```
sudo service docker start
sudo systemctl start docker
```
### 国内源
```
$ vi /etc/docker/daemon.json
{
"registry-mirrors":[ "https://registry.docker-cn.com" ]
}
$ systemctl restart docker
```

641
docker/3 常用命令.md Normal file
View File

@@ -0,0 +1,641 @@
## 0 基本命令
### 概述
![](image/2022-10-07-17-00-05.png)
```
[root@192 home]# docker --help
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:
--config string Location of client config
files (default "/root/.docker")
-c, --context string Name of the context to use to
connect to the daemon
(overrides DOCKER_HOST env var
and default context set with
"docker context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level
("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by
this CA (default
"/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file
(default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default
"/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
context Manage contexts
engine Manage the docker engine
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
```
```shell
docker version 查看版本号
docker info 查看基本信息
docker 命令 --help 查看帮助命令
```
## 1 镜像命令
### docker images 查看镜像
查看所有本地主机上的镜像
```shell
~docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 6e0e1ad86723 3 hours ago 478MB
# 解释
REPOSITORY # 镜像仓库源
TAG # 镜像的标签
IMAGE ID # 镜像的ID
CREATED # 镜像的创建时间
SIZE # 镜像的大小
--all , -a Show all images (default hides intermediate images) # 显示所有
--quiet , -q Only show numeric IDs # 只显示id
```
### docker search 搜索镜像
```shell
docker search catainer_name:tag
docker search mysql --filter=STARS=3000 # 搜索出Stars大于3000的
➜ ~ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13234 [OK]
mariadb MariaDB Server is a high performing open sou… 5062 [OK]
```
### docker pull 下载镜像
* 分层下载同一个镜像不同的tag可以共用之前的分层。
```
docker pull catainer_name:tag
Using default tag: latest # 如果不写tag默认就是latest
latest: Pulling from library/mysql
051f419db9dd: Pull complete # 分层下载
7627573fa82a: Pull complete
a44b358d7796: Pull complete
95753aff4b95: Pull complete
a1fa3bee53f4: Pull complete
f5227e0d612c: Pull complete
b4b4368b1983: Pull complete
f26212810c32: Pull complete
d803d4215f95: Pull complete
d5358a7f7d07: Pull complete
435e8908cd69: Pull complete
Digest: sha256:b9532b1edea72b6cee12d9f5a78547bd3812ea5db842566e17f8b33291ed2921 # 签名信息
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
```
### docker rmi删除镜像
```
删除指定的容器
docker rmi -f image_id
# 删除所有的镜像
docker rmi -f $(docker images -aq)
```
### docker image 打包镜像
Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image。
```
# 列出本机的所有 image 文件。
$ docker image ls
# 删除 image 文件
$ docker image rm [imageName]
```
image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件,而不是自己制作。即使要定制,也应该基于别人的 image 文件进行加工,而不是从零开始制作。
为了方便共享image 文件制作完成后可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。此外,出售自己制作的 image 文件也是可以的。
## 2 容器命令
### docker run 启动镜像
```bash
docker run [] image
# 参数说明
--name="Name" 容器名字,,同一个镜像可以由多个不同的容器。
-d 后台方式运行
-it 使用交互方式运行。金融容器查看内容
-p 指定容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口puu
-p ip:主机端口:容器端口
-P 随机指定端口
exit
退出容器。如果交互形式运行,退出后容器就会终止。
```
### docker ps查看容器
* 查看正在运行的容器
```
docker ps
-a 所有运行的容器,包括停止的容器。历史运行过的容器
-n=? 显示最近创建的容器
-q 只显示容器的编号。
➜ ~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11283b603c39 centos "/bin/bash" 3 minutes ago Exited (0) 5 seconds ago vibrant_tereshkova
```
### 退出容器
```
exit 容器停止退出
ctrl +p +q 容器不停止退出
[root@192 ~]# docker run -it centos /bin/bash
[root@bfcea13c40cd /]# [root@192 ~]# docker ps ##注意这里会自动给个命令,删掉
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bfcea13c40cd centos "/bin/bash" About a minute ago Up About a minute stoic_wilson
edbd9366d959 centos "/bin/bash" 7 minutes ago Up 7 minutes affectionate_bartik
[root@192 ~]# docker exec -it edbd9366d959 /bin/bash ## 再次进入
[root@edbd9366d959 /]# exit ##停止并推出
exit
```
### docker rm删除容器
*
```
docker rm container_id 删除指定的容器,不能删除正在运行的容器。
-f 可以删除正在运行的容器
-f $(docker ps -aq) 删除所有的容器。包括没在运行的容器
docker -aq |xargs docker rm 也能删除容器
```
### 启动、停止容器
```
docker start container_id 启动容器
docker restart container_id 重启容器
docker stop container_id 停止当前正在运行容器
docker kill container_id 强制停止当前容器
```
## 3 其他命令
### 后台启动容器
```
docker run -d centos
* docker run -d 后台运行但是镜像停止了。后台运行就必须有一个前台进程docker发现没有提供服务或者没有程序应用会自动停止。
```
### docker logs查看日志
* 显示指定条数的日志
```
➜ ~ docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
```
```
➜ ~ docker run -d centos /bin/sh -c "while true;do echo zhangxiaoyu;sleep 1;done"
9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e594a93bc17 centos "/bin/sh -c 'while t…" 8 seconds ago Up 7 seconds quizzical_proskuriakova
2b4e3ea3e31f nginx "/docker-entrypoint.…" About an hour ago Up About an hour k8s_nginx_nginx-deployment-544dc8b7c4-5lkjz_default_87eff95b-e6da-444b-b4ed-5e25e15f3ce7_2
2fadcdb7bb51 804f9cebfdc5 "/docker-entrypoint.…" About an hour ago Up About an hour k8s_web-server_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a7d8795f243c luksa/fortune "/bin/sh -c /bin/for…" About an hour ago Up About an hour k8s_html-generator_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a40e11d2f769 115053965e86 "/metrics-sidecar" About an hour ago Up About an hour k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-8c47d4b5d-wht26_kubernetes-dashboard_c2a0ead5-956b-4bb3-929d-d329c118759a_1
➜ ~ docker logs -tf --tail 10 9e594a93bc17
2022-10-07T08:38:09.202722580Z zhangxiaoyu
2022-10-07T08:38:10.204883524Z zhangxiaoyu
2022-10-07T08:38:11.209016595Z zhangxiaoyu
2022-10-07T08:38:12.216470402Z zhangxiaoyu
```
### 查看进程信息ps/top
```
docker top 容器id
➜ ~ docker top 9e594a93bc17
UID PID PPID C STIME TTY TIME CMD
root 79688 79663 0 08:36 ? 00:00:00 /bin/sh -c while true;do echo zhangxiaoyu;sleep 1;done
root 84352 79688 0 08:41 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
```
### docker inspect查看容器的元数据
```
➜ ~ docker inspect 9e594a93bc17
[
{
"Id": "9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed",
"Created": "2022-10-07T08:36:30.660739121Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true;do echo zhangxiaoyu;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 79688,
"ExitCode": 0,
"Error": "",
"StartedAt": "2022-10-07T08:36:31.008595764Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"ResolvConfPath": "/var/lib/docker/containers/9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed/hostname",
"HostsPath": "/var/lib/docker/containers/9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed/hosts",
"LogPath": "/var/lib/docker/containers/9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed/9e594a93bc178f0eb6bb22e3abbf730ecf30f992b74eb95942366339924b14ed-json.log",
"Name": "/quizzical_proskuriakova",
"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": "private",
"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": null,
"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/708ae2078ad7240a47648c22eea4fa1768a119adcb8d0bf123d46a8dd19e5063-init/diff:/var/lib/docker/overlay2/96cb8d4ebc60b000a56aa04a929228cb062524eaa54df1b98d3dc7e71de7d296/diff",
"MergedDir": "/var/lib/docker/overlay2/708ae2078ad7240a47648c22eea4fa1768a119adcb8d0bf123d46a8dd19e5063/merged",
"UpperDir": "/var/lib/docker/overlay2/708ae2078ad7240a47648c22eea4fa1768a119adcb8d0bf123d46a8dd19e5063/diff",
"WorkDir": "/var/lib/docker/overlay2/708ae2078ad7240a47648c22eea4fa1768a119adcb8d0bf123d46a8dd19e5063/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "9e594a93bc17",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"while true;do echo zhangxiaoyu;sleep 1;done"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "3afb645e146a65c60e82b5662c52cead5baa6b44534e6377fc494b9724c4097b",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/3afb645e146a",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "51fc6f4ddc503db0c5ab935614f21d99ec1a464b93398ddf2197a4bb10068873",
"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": "70b0ebbcbbdf0e90289563aaedcbdd8b55e347ab1cc818cf1ee4c18564d5d2e1",
"EndpointID": "51fc6f4ddc503db0c5ab935614f21d99ec1a464b93398ddf2197a4bb10068873",
"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
}
}
}
}
]
```
### 进入正在运行的容器
* docker exec 容器id
* 进入容器后开启新的终端
* docker attach 容器id
* 进入容器中正在执行的终端,不会启动新的进程。
```
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e594a93bc17 centos "/bin/sh -c 'while t…" 9 minutes ago Up 9 minutes quizzical_proskuriakova
2b4e3ea3e31f nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours k8s_nginx_nginx-deployment-544dc8b7c4-5lkjz_default_87eff95b-e6da-444b-b4ed-5e25e15f3ce7_2
2fadcdb7bb51 804f9cebfdc5 "/docker-entrypoint.…" 2 hours ago Up 2 hours k8s_web-server_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a7d8795f243c luksa/fortune "/bin/sh -c /bin/for…" 2 hours ago Up 2 hours k8s_html-generator_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a40e11d2f769 115053965e86 "/metrics-sidecar" 2 hours ago Up 2 hours k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-8c47d4b5d-wht26_kubernetes-dashboard_c2a0ead5-956b-4bb3-929d-d329c118759a_1
➜ ~ docker exec -it 9e594a93bc17 /bin/bash
[root@9e594a93bc17 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
```
```
docker attach containerid
```
### docker cp从容器内拷贝到主机上
* docker cp id
* 进入容器,
* 创建文件
* 拷贝文件
```sh
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e594a93bc17 centos "/bin/sh -c 'while t…" 15 minutes ago Up 15 minutes quizzical_proskuriakova
2b4e3ea3e31f nginx "/docker-entrypoint.…" 2 hours ago Up 2 hours k8s_nginx_nginx-deployment-544dc8b7c4-5lkjz_default_87eff95b-e6da-444b-b4ed-5e25e15f3ce7_2
2fadcdb7bb51 804f9cebfdc5 "/docker-entrypoint.…" 2 hours ago Up 2 hours k8s_web-server_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a7d8795f243c luksa/fortune "/bin/sh -c /bin/for…" 2 hours ago Up 2 hours k8s_html-generator_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2
a40e11d2f769 115053965e86 "/metrics-sidecar" 2 hours ago Up 2 hours k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-8c47d4b5d-wht26_kubernetes-dashboard_c2a0ead5-956b-4bb3-929d-d329c118759a_1
➜ ~ docker exec -it 9e594a93bc17 /bin/bash
[root@9e594a93bc17 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@9e594a93bc17 /]# cd home
[root@9e594a93bc17 home]# ls
[root@9e594a93bc17 home]# touch zhangxiaoyu.go
[root@9e594a93bc17 home]# ls
zhangxiaoyu.go
[root@9e594a93bc17 home]# exit
exit
➜ ~ docker cp 9e594a93bc17:/home/zhangxiaoyu.go ./
➜ ~ ls
Applications Pictures conf input_stream mybin
Desktop Postman Agent dsrconsole_extract java_error_in_idea.hprof open_code
Documents Public gitee java_error_in_idea_32040.log schedule
Downloads Zotero github kubeadm sprint_MS_S916382437_20201014_zhonghang
IdeaProjects a.txt hello.json kubectl.sha256 temp
Library antdld-resources hello.txt localFileRegistry work
Movies app htdocs logs zhangxiaoyu.go
Music bower_test html mosn zhonghang_project
```
### docker stats查看状态
* 每秒刷新查看容器状态。
```
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
7b8096067457 tomcat02 0.86% 118.8MiB / 7.676GiB 1.51% 11.1kB / 159kB 0B / 6.14MB 41
083dfca4b050 tomcat01 0.17% 67.57MiB / 7.676GiB 0.86% 1.05kB / 0B 0B / 328kB 40
99d1cdedb54a nginx01 0.00% 5.352MiB / 7.676GiB 0.07% 4.03kB / 3.66kB 0B / 12.3kB 7
9e594a93bc17 quizzical_proskuriakova 0.44% 952KiB / 7.676GiB 0.01% 1.45kB / 0B 0B / 8.19kB 2
2b4e3ea3e31f k8s_nginx_nginx-deployment-544dc8b7c4-5lkjz_default_87eff95b-e6da-444b-b4ed-5e25e15f3ce7_2 0.00% 5.371MiB / 7.676GiB 0.07% 0B / 0B 0B / 12.3kB 7
2fadcdb7bb51 k8s_web-server_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2 0.00% 6.508MiB / 7.676GiB 0.08% 0B / 0B 6.48MB / 12.3kB 7
a7d8795f243c k8s_html-generator_fortune_default_ff6246d7-788f-4807-a649-807cf65ae492_2 0.00% 5.113MiB / 7.676GiB 0.07% 0B / 0B 6.23MB / 3.83MB 3
a40e11d2f769 k8s_dashboard-metrics-scraper_dashboard-metrics-scraper-8c47d4b5d-wht26_kubernetes-dashboard_c2a0ead5-956b-4bb3-929d-d329c118759a_1 0.00% 6.793MiB / 7.676GiB 0.09% 0B / 0B 22.9MB / 0B 10
```
## 实例nginx容器
1. 搜索镜像search
2. 下载镜像pull
3. 创建运行run -d 后台运行--name 名称-p port端口映射
4. 查看运行ps /curl
5. 进入容器exec /attach
端口映射的原理
![](image/2022-10-07-17-23-16.png)
> run --rm stop后删除
> run -e 添加启动参数和启动环境参数
## 实例es+kibana
* 两个容器可以通过端口映射和内网ip访问彼此的服务。
![](image/2022-10-07-21-43-13.png)
### 可视化portainer
```
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/po
rtainer
```

View File

@@ -1,15 +0,0 @@
六、image 文件
Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image。
```
# 列出本机的所有 image 文件。
$ docker image ls
# 删除 image 文件
$ docker image rm [imageName]
```
image 文件是通用的,一台机器的 image 文件拷贝到另一台机器,照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的 image 文件,而不是自己制作。即使要定制,也应该基于别人的 image 文件进行加工,而不是从零开始制作。
为了方便共享image 文件制作完成后可以上传到网上的仓库。Docker 的官方仓库 Docker Hub 是最重要、最常用的 image 仓库。此外,出售自己制作的 image 文件也是可以的。

38
docker/4 分层文件.md Normal file
View File

@@ -0,0 +1,38 @@
## 1 分层文件系统
### UnionFS 联合文件系统
* bootfsboot file system
* rootfsroot file system
![](image/2022-10-07-21-46-07.png)
### 分层文件系统
![](image/2022-10-07-21-46-56.png)
![](image/2022-10-07-21-47-04.png)
![](image/2022-10-07-21-47-30.png)
![](image/2022-10-07-21-47-37.png)
* Docker镜像都是只读的当容器启动时一个新的可写层被加到镜像的顶部这一层就是我们通常说的容器层容器层之下的都叫镜像层
![](image/2022-10-07-21-48-06.png)
## 2 commit提交镜像
```
docker commit # 提交容器成为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
```
* 创建新镜像
```
➜ ~ docker commit -a="zhangxiaoyude" -m="add webapps app" 7b8096067457 tomcat02:1.0
sha256:6e0e1ad86723c435bdf26d368472195b7050de1d6b920252d9c93eac26132336
➜ ~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 6e0e1ad86723 20 seconds ago 478MB
```
* 查看新镜像。发现新的版本,比之前的大了一些,因为里面记录了我们的改动
![](image/2022-10-07-21-51-04.png)

View File

@@ -1,18 +0,0 @@
## 定义
- 镜像ImageDocker 镜像Image就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器Container镜像Image和容器Container的关系就像是面向对象程序设计中的类和实例一样镜像是静态的定义容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库Repository仓库可看成一个代码控制中心用来保存镜像。
![](img/docker-structure.png)
## 概念
* Docker 镜像(Images)Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
* Docker 容器(Container)容器是独立运行的一个或一组应用,是镜像运行时的实体。
* Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
* Docker 主机(Host)一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
* Docker 仓库RegistryDocker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。
* Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库Repository每个仓库可以包含多个标签Tag每个标签对应一个镜像。通常一个仓库会包含同一个软件不同版本的镜像而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
* Docker Machine。Docker Machine是一个简化Docker安装的命令行工具通过一个简单的命令行即可在相应的平台上安装Docker比如VirtualBox、 Digital Ocean、Microsoft Azure。

120
docker/5 容器数据卷.md Normal file
View File

@@ -0,0 +1,120 @@
## 1 概述
### 原理
* Docker将应用和环境打包成一个镜像
* 数据?如果数据在容器中,那么我们容器删除,数据就会丢失。需求:数据持久化。
* 所以Mysql的数据可以存储在本地。
* 所以:容器间可以有一个数据共享的技术。 Docker容器中产生的数据同步到本地。这就是卷技术。
* 本质上是一种目录挂载,将容器内的目录,挂载到宿主机上。
![](image/2022-10-07-22-09-15.png)
![](image/2022-10-07-23-03-03.png)
**总结:容器的持久化和同步操作,容器间可以数据共享**
### 使用
* -v 实现文件映射
```
docker run -it -v 目录映射 -p 端口映射
# -it 交互式
# -v volume卷技术
# -p 主机端口
➜ ~ docker run -it -v /Users/yinkanglong/ceshi:/home centos /bin/bash
```
* 使用docker inspect 查看挂载情况mount
![](image/2022-10-07-23-05-38.png)
![](image/2022-10-07-23-06-50.png)
* 同步的过程,是一种双向绑定的过程。容器停止后,修改主机文件,再启动容器的时候,数据同样改变
![](image/2022-10-07-22-09-28.png)
> 是同步的过程,还是目录挂载到磁盘的同一个位置了?
### 实战安装Mysql
```
# 获取镜像
docker pull mysql 5.7
# 运行容器,需要做数据挂载
-d 后台运行
-p 端口映射
-v 卷挂载
--name 容器名字
➜ ~ docker run -d -p 3310:3306 -v /Users/yinkanglong/mysql/conf:/etc/mysql/conf.d -v /Users/yinkanglong/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动之后链接数据库服务器进行测试
➜ data mysql -h 127.0.0.1 -P 3310 -uroot -p123456
# 在本地测试创建数据库,查看映射路径是否可以
create table
```
![](image/2022-10-07-22-43-49.png)
## 2 docker volume数据卷操作
```
docker volume --help
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
```
* 查看所有的卷的情况
```
➜ docker volume ls
DRIVER VOLUME NAME
local 635d632e8d79ad10168a6bd6b65ba5b67de68c38c63b619915b6d00db2bd1b4a
local 0704fe09fca1d196b4d4f1cc14141ba05bae986d03ac1209f63ed1cca3d7bd7c
local 924b3cbb61444c73191a11200c727b52f9ccc17dd27024bce61ba63a33577663
# 这里发现的,就是匿名挂载。
```
* 查看卷的配置信息
```
➜ docker volume inspect 635d632e8d79ad10168a6bd6b65ba5b67de68c38c63b619915b6d00db2bd1b4a
[
{
"CreatedAt": "2022-10-07T10:04:09Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/635d632e8d79ad10168a6bd6b65ba5b67de68c38c63b619915b6d00db2bd1b4a/_data",
"Name": "635d632e8d79ad10168a6bd6b65ba5b67de68c38c63b619915b6d00db2bd1b4a",
"Options": null,
"Scope": "local"
}
]
```
### 多种挂载方式
匿名挂载和具名挂载
* 匿名挂载volume名称是随机生成的字符串。没有指定目录的情况下都是挂载在/var/lib/docker/volumes/xxxx目录下
* 具名挂载方式volume名称是我们指定的字符串。可以很方便地找我们的卷。大多数情况下使用具名挂载。
* 指定路径挂载。
* 指定读写权限挂载。容器内对路径的读写权限
* ro readonly 只读权限
* rw readwrite 读写权限
```
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机绝对路径:容器内路径 # 指定路径挂载
-v ::读写权限 # 指定目录的读写权限。
```
```
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
```
## 3 DockerFile构建docker镜像文件
## 4

81
docker/6 DockerFile.md Normal file
View File

@@ -0,0 +1,81 @@
## 概念
### 简介
* Docker将应用和环境打包成一个镜像
* 数据?如果数据在容器中,那么我们容器删除,数据就会丢失。需求:数据持久化。
* 所以Mysql的数据可以存储在本地。
* 所以:容器间可以有一个数据共享的技术。 Docker容器中产生的数据同步到本地。
* 这就是卷技术目录挂载将容器内的目录挂载到Linux上。
![](image/2022-10-07-22-09-15.png)
**总结:容器的持久化和同步操作**
### 使用
* -v 实现文件映射
```
docker run -it -v 目录映射 -p 端口映射
➜ ~ docker run -it -v /Users/yinkanglong/ceshi:/home centos /bin/bash
```
* 使用docker inspect 查看挂载情况mount
* 同步的过程,是一种双向绑定的过程。
![](image/2022-10-07-22-09-28.png)
> 是同步的过程,还是目录挂载到磁盘的同一个位置了?
### 实战安装Mysql
```
# 获取镜像
docker pull mysql 5.7
# 运行容器,需要做数据挂载
-d 后台运行
-p 端口映射
-v 卷挂载
--name 容器名字
➜ ~ docker run -d -p 3310:3306 -v /Users/yinkanglong/mysql/conf:/etc/mysql/conf.d -v /Users/yinkanglong/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动之后链接数据库服务器进行测试
➜ data mysql -h 127.0.0.1 -P 3310 -uroot -p123456
# 在本地测试创建数据库,查看映射路径是否可以
create table
```
![](image/2022-10-07-22-43-49.png)
## 概念原理
### docker volume数据卷操作
```
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
```
* 查看所有的卷的情况
```
➜ data docker volume ls
DRIVER VOLUME NAME
local 635d632e8d79ad10168a6bd6b65ba5b67de68c38c63b619915b6d00db2bd1b4a
local 0704fe09fca1d196b4d4f1cc14141ba05bae986d03ac1209f63ed1cca3d7bd7c
local 924b3cbb61444c73191a11200c727b52f9ccc17dd27024bce61ba63a33577663
# 这里发现的,就是匿名挂载。
```
### 匿名挂载
```
# 匿名挂载
```

0
docker/7 Docker网络.md Normal file
View File

0
docker/8 IDEA整合.md Normal file
View File

0
docker/9 Composed.md Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB