Docker Study

Docker Study

Docker 的安装

在 centOS7 上安装 docker。我们通过访问 docker 的帮助文档网站 https://docs.docker.com,在这里面选择 engine -> install -> contos,或者我们直接可以访问 https://docs.docker.com/engine/install/centos/ 来寻找到 contos 的 docker 容器的安装方式。

在安装 docker 之前我们需要先在物理机上卸载旧的版本

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 \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新 yum 索引

yum makecache fast

安装 docker 相关的程序

sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

启动 docker

systemctl start docker

而后可以使用 docker version 查看是否安装成功

运行 hello world 实例

docker run hello-world

查看 hello world 的镜像

docker images

卸载 docker

# 卸载依赖
sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 删除资源
# /var/lib/docker 为 docker 的工作目录
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

docker 配置阿里云镜像加速

每个人都有自己的镜像加速地址。这里是要登陆阿里云的账号在阿里云的网站里面开通,这里自行百度即可找到。

Docker run 的运行流程

我们在执行 docker run 的时候,首先会在本得寻找镜像,如果在本地找到了这个镜像,那么就会运行本地的这个镜像。如果本地没有找到镜像,则会到 docker hub 上寻找我们所要运行的镜像。如果在 docker hub 上寻找到了我们所要运行的镜像,那么就会下载到本地运行,否者就会报错。

底层原理

docker 是怎么工作的?

Docker 是一个 Client - Server 结构系统,Docker 的守护进程运行在主机上。通过 Socket 从客户端访问。

DockerServer 在接收到 DockerClient 的指令之后,就会执行这个命令。

docker 为什么比 vm 快?

  1. Docker 有着比虚拟机更小的抽象层。

  2. Docker 利用的宿主机的内核,VM 使用的是 Guest OS。

    所以新建一个容器的时候,docker 不需要像虚拟机一样加载一个操作系统内核。避免一个引导性的操作。虚拟机是加载 Guest OS,是分钟级的操作,而 docker 是利用宿主机的操作系统,这就会省略掉了那个复杂的过程,是秒级的启动。

Docker 的常用命令

帮助命令

docker version # 显示 docker 的版本信息
docker info # 显示 docker 的系统信息,包括镜像和容器的数量
docker 命令 --help # 万能命令

镜像命令

docker images 查看所有本地主机上的镜像

[root@niuma ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xiaocubao-app latest 9c4df2de491a 5 weeks ago 164MB
xiaocubao-api latest 74e024e86c6c 5 weeks ago 417MB
mysql latest c2c2eba5ae85 2 months ago 535MB
mysql 5.7 14905234a4ed 2 months ago 495MB
nginx latest 605c77e624dd 12 months ago 141MB
node 16-slim 13cc87dcb313 12 months ago 174MB
redis latest 7614ae9453d1 12 months ago 113MB
hub.c.163.com/housan993/centos7_jdk8 latest 0f793ba5281b 4 years ago 356MB
# 可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的 id
字段名 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的 ID
CREATED 创建时间
SIZE 镜像的大小

docker search 搜索镜像

[root@niuma ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13619 [OK]
mariadb MariaDB Server is a high performing open sou… 5200 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 713 [OK]
percona Percona Server is a fork of the MySQL relati… 597 [OK]
bitnami/mysql Bitnami MySQL Docker Image 80 [OK]
databack/mysql-backup Back up mysql databases to... anywhere! 77
linuxserver/mysql-workbench 45
ubuntu/mysql MySQL open source fast, stable, multi-thread… 40
linuxserver/mysql A Mysql container, brought to you by LinuxSe… 38
circleci/mysql MySQL is a widely used, open-source relation… 28
google/mysql MySQL server for Google Compute Engine 22 [OK]
rapidfort/mysql RapidFort optimized, hardened image for MySQL 13
bitnami/mysqld-exporter 4
ibmcom/mysql-s390x Docker image for mysql-s390x 2
vitess/mysqlctld vitess/mysqlctld 1 [OK]
newrelic/mysql-plugin New Relic Plugin for monitoring MySQL databa… 1 [OK]
hashicorp/mysql-portworx-demo 0
rapidfort/mysql-official RapidFort optimized, hardened image for MySQ… 0
docksal/mysql MySQL service images for Docksal - https://d… 0
mirantis/mysql 0
rapidfort/mysql8-ib RapidFort optimized, hardened image for MySQ… 0
cimg/mysql 0
eclipse/mysql Mysql 5.7, curl, rsync 0 [OK]
drud/mysql 0
silintl/mysql-backup-restore Simple docker image to perform mysql backups… 0 [OK]
# 可选项,通过收藏来过滤镜像
--filter=STARS=300 # 搜索出来的镜像是 STARS 大于 3000 的
[root@niuma ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13619 [OK]
mariadb MariaDB Server is a high performing open sou… 5200 [OK]

docker pull 下载镜像

下载 docker 镜像的命令:

docker pull <镜像名>[:tag]

# 下载 mysql 镜像
docker pull mysql # 如果没有添加 tag,默认就是 latest
docker pull mysql:5.7 # 指定 tag 下载版本

docker rmi 删除镜像

docker rmi -f <镜像id> 或 <镜像名字> # 删除指定的镜像
docker rmi -f <镜像id> <镜像id> <镜像id> # 删除多个镜像
# 查询出所有的镜像 id 而后进行递归删除
docker rmi -f $(docker images -aq) # 删除所有的镜像

容器命令

说明:我们有了镜像才可以创建容器,linux,下载一个 centos 镜像来测试学习

docker pull cnetos

创建容器并启动

docker run [可选参数] image
# 参数说明
--name="Name" # 定义容器的名字,用来区分容器
-d # 以后台的方式运行
-it # 使用交互的方式运行,进入容器查看内容
-p # 指定端口映射
-P # 随机指定端口
# 启动并进入容器 docker run -it contos /bin/bash
[root@niuma ~]# docker run -it centos /bin/bash
[root@fbd382515bb9 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退会主机
[root@fbd382515bb9 /]# exit
exit

查看正在运行的容器

docker ps # 查看正在运行的容器
-a # 查看正在运行的容器和历史运行过的容器
-q # 之显示容器的编号
-n=? # 显示最近创建的容器 类似 SQL 中的 limit

容器的退出

exit # 直接停止容器并退出
# 如果想要容器退出后不停止运行,则使用快捷点 ctrl + p + q

删除容器

docker rm <容器id> # 删除指定的容器,但是不能删除正在运行的容器,如果要强制删除则 rm -f
docker rm $(docker ps -aq) # 删除所有的容器
docker ps -a -q | xargs docker rm # 删除所有的容器

启动和停止容器

docker start <容器id> # 启动一个已停止的容器
docker resart <容器id> # 重启一个容器
docker stop <容器id> # 停止一个正在运行的容器
docker kill <容器id> # 强行停止一个容器

常用的其他命令

后台启动容器

docker run -d <镜像名>

如果我们使用 docker run -d centos 这个命令来后台启动 centOS 的话,我们使用 docker ps 来查看正在运行的容器,我们是无法查看到的。我们发现 centos 这个容器已经停止运行了。因为 docker 容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用,或者发现自己没有提供服务,那么就会立刻停止。

查看日志

docker logs -tf <容器> # 显示日志
docker logs -tf --tail <number> <容器> # 要显示日志的条数

查看容器中的进程信息

docker top <容器>

查看镜像元数据

docker inspect <容器>

进入当前正在运行的容器

容器通常是以后台的方式进行运行的,如果我们需要进入容器修改一些配置,则需要使用 docker exec 命令

docker exec -it <容器> [bash or shell] # docker exec -it mysql /bin/bash
docker attach <容器>
# docker exec 进入容器后开启一个新的终端,可以在里面操作
# docker attach 进入容器正在运行的终端,不会启动新的进程

从容器中拷贝文件到主机上

docker cp <容器>:容器内路径 目的主机路径

使用 Docker 安装 Nginx

# 查询镜像
docker search nginx
# 获取 Nginx 镜像
docker pull nginx
# 启动 Nginx
docker run -d --name nginx01 -p 80:80 nginx
# -d 后台运行
# --name 给容器定义一个名字
# -p 宿主机和容器的端口映射

镜像

镜像是什么?

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。它包含运行某个软件所需要的所有内容,包括代码和运行时的库和环境变量及配置文件。

所有的应用打包成 docker 镜像就可以直接跑起来。

如何得到镜像:

  • 从远程仓库下载
  • 从他人那里拷贝
  • 自己使用 DockerFile 制作一个镜像

Docker 镜像加载原理

UnionFS(联合文件系统)

我们在下载镜像的时候看到的就是这个联合文件系统。

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

Docker 镜像加载原理

docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称之为 UnionFS。

BootFS(boot file system)主要包含 BootLoader 和 Kernel, BootLoader主要是引导加载Kernel。 Linux 刚启动的时候会加载 BootFS 文件系统,在 Docker 镜像的最底层是 BootFS。这一层与我们经典的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 BootFS 转交给内核,此时系统也会卸载 BootFS。

RootFS(root file system), 在 BootFS 之上。包含的就是典型 Linux 系统中的 /dev /proc /bin /etc 等标准目录和文件。RootFS 就是各种不同的操作系统发行版,比如 Ubuntu,CentOS 等。

对于一个精简的 OS,RootFS 可以很小,只需要包含最基本的命令、工具和库就可以了。因为底层直接使用 Host 的 Kernel, 自己只需要提供 RootFS 就可以了。由此可见对于不同的 Linux 发行版,BootFS 基本是一致的,RootFS 会有差别,因此不同的发行版可以公用 BootFS。

commit 镜像

docker commit 提交容器成为一个新的副本

# 命令和 git 原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

我们在什么时候使用 commit 命令呢?我们在一个容器中修改了某些操作之后,我们就可以使用 commit 命令进行提交,提交之后就可以在本地的 docker 仓库中看到我们新提交的镜像。这样我们就可以直接使用这个镜像。

容器数据卷

docker 将应用和环境打包成一个镜像。我们运行容器产生的数据是在容器中的,如果我们将容器删除了,那么数据也会随之消失。所以我们需要将数据持久化的进行保存。在容器之间有一个数据共享的技术。Docker 容器中的数据同步到本地。这个就是卷的技术。对目录进行挂载,将容器中的目录挂载到本地 Linux 上。

容器的持久化和同步操作,容器间也是可以数据共享的

使用数据卷

方式一,直接使用命令来挂载 -v

docker run -it -v 主机目录:容器内目录

使用了数据卷技术之后,这两个文件夹就会相互绑定,和 vue 中的双向绑定是一样的。如果容器中的目录发生了变化,宿主机上的文件也会发生变化。宿主机上的文件发生变化,容器中的文件同样会发生变化。

mysql 数据同步

# 获取 mysql5.7 的镜像
docker pull mysql:5.7
# 启动 mysql
docker run -d -p 3306:3306 -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Root123. --name mysql57 mysql:5.7
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名

具名挂载和匿名挂载

# 匿名挂载
-v <容器内的路径>
docker run -d -p --name nginx -v /etc/nginx nginx
# 查看所有的 volume 的情况
docker volume
[root@niuma ~]# docker volume ls
DRIVER VOLUME NAME
local 0bcd8a551caed35715e6bdebf00a2890c33aea9754e54c7f2ba9e76331d2666b
local 1e05d5e74424f88896d97c00e7082f30c5719fb8d27aedf72a2604f126eeed1e
local 04f48cd3c7ecdd2f6a28d1dffc49dae68925aaad5dad7897f1743d755234c2a4
local 70c04e97600983e91e88e406ac82183fa328963d496c4826ea85733f696728df
local d0e620452fbd54146b99129060bd5a96af46395797f0bf72043aa50005c60981
local fc52d67a903f96bc3337604b9d1ec910076216e41ff46d44fadf3e58ce870903
# 这里我们发现,这种就是匿名挂载,我们在 -v 只写了容器内部路径,没有写容器外部的路径。

如何确定是具名挂载还是匿名挂载或是指定路径挂载

  • -v <容器内部路径> 是匿名挂载
  • -v <卷名>:<容器内部路径> 是具名挂载
  • -v <宿主机路径>:<容器内部路径> 是指定路径挂载

拓展

# 通过 -v 容器内路径:ro rw 改变读写权限
ro read only # 只读
rw read write # 可读可写
# 一旦设置了容器的权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx01 -v nginx01:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v nginx02:/etc/nginx:rw nginx
# ro 只要看到了 ro 就说明这个路径只能通过宿主机来操作,容器内部是无法操作的。

数据卷容器

使用 --volumes-form 来对两个容器之间的数据进行同步。

这种关系属于是继承的关系

例如实现两个 mysql 的数据共享

docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7

这个时候就可以实现两个数据之间的数据同步。

容器之间的信息传递,数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦你持久化到本地,这个时候,本地的数据是不会删除的。

DockerFile

DockerFile 介绍

DockerFile 是用来构建 docker 镜像的文件,它就是一个命令参数脚本。

构建步骤:

  1. 编写一个 dockerfile 文件
  2. docker build 构建一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(DockerHub、阿里云镜像仓库)

DockerFile 构建过程

基础知识:

  1. 每一个保留的关键字(指令)都必须是大写字母。
  2. 执行从上到下执行顺序。
  3. "#" 表示注释
  4. 每一个指令都会创建提交一个新的镜像层,并提交 。

DockerFile 的指令

指令 解释
FROM 指定基础镜像
MAINTAINER 镜像作者,name and email
run 镜像构建的时候需要运行的命令
ADD 添加内容
WORKDIR 镜像的工作目录
VOLUME 挂载的目录
EXPOSE 保留端口配置
CMD 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令。
COPY 类似 ADD 将我们的文件拷贝到镜像中。
ENV 构建的时候设置环境变量

创建一个自己的 CentOS

我们知道官方的 CentOS 这个镜像是压缩版的,有的命令是没有的,例如 vim 和 ifconfig 命令都是没有的,那么我们现在构建一个自定义的镜像。

FROM centos:centos7
MAINTAINER niuma<2493378918@qq.com>
ENV MYPATH /user/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "------end------"
CMD /bin/bash

然后我们构建这个镜像

docker build -f mydockerfile -t mycentos:1 .

这个时候我们就可以在我们的在本地镜像中看到我们新构建的镜像了。

运行这个镜像

docker run -it mycentos:1

这个时候我们发现我们的工作目录是自定义的 /usr/local

然后 ifconfigvim 命令都是可以正常使用的。

构建一个 tomcat 镜像

我们先将 java 和 tomcat 的压缩包上传到服务器,然后创建 readme.txt(非必要),然后编写 dockerfile, dockerfile 的文件名使用官方的命名规则 Dockerfile 这样在构建的时候就会自动寻找到这个文件。

FROM centos
MAINTAINER NiuMa<2493378918@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u291-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.59.tar.gz /usr/local/
# RUN yum -y install vim
ENV MYPATH /usr/lcoal
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_291
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.59
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.59
ENV PATH $PATH:$JAVA_HOME/bin:CATALINA_HOME/bin:CATALINA_HOME/lib
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.59/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.59/bin/logs/catalina.out

Docker 网络

理解 Docker 网络(Docker0)

我们在服务器上使用 ip add 命令,可以看到有三个网络环境。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:0a:4b:52 brd ff:ff:ff:ff:ff:ff
inet 172.27.140.124/20 brd 172.27.143.255 scope global dynamic eth0
valid_lft 309344516sec preferred_lft 309344516sec
inet6 fe80::216:3eff:fe0a:4b52/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:a9:69:8f:fc brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:a9ff:fe69:8ffc/64 scope link
valid_lft forever preferred_lft forever

在这其中有个 docker0 的网络,这个就是 docker 的内部的网络环境。

docker 是如何处理容器网络访问的?

首先我们来测试一下我们是否能够在服务器上 ping 通 docker 中的网络。

运行一个 tomcat 容器。

docker run -d -P --name tomcat01 tomcat

启动 tomcat 之后查看容器内的 ip 地址

docker exec -it tomcat01 ip addr

如果使用这个命令报错找不到 Ip 命令

OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown

就是用如下命令

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' tomcat01

然后我们就可以得到一个 ip 地址

[root@niuma ~]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' tomcat01
172.17.0.6

然后我们 ping 这个 ip,发现是可以 ping 通的,由此可以得出结论是服务器是可以 ping 通容器中的网络的。

原理

  1. 我们每启动一个 docker 容器,docker 就会给 docker 容器分配一个 ip ,我们只要安装了 docker, 就会有一个网卡 docker0。使用的连接方式是桥接,用的是 evth-pair
  2. 我们在启动一个容器的时候,使用 ip addr 命令会法相多了一对网卡。这时候我们会发现这个容器带来的网卡是成对出现的,都是一对一对的。 evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连。正是应为有这样的特性,evth-pair 充当了一个桥梁,连接着各种虚拟网络设备。

自定义网络

查看所有的 docker 网络

[root@niuma ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
30d5a53144df bridge bridge local
8482e981e677 host host local
c22900e02edd none null local
name detail
bridge 桥接 docker(default)
none 不配置网络
host 主机模式,和宿主机共享网络
container 容器网络连通(用得少)

创建一个网络

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 niumanet

如果运行这个命令没有报错出现了一串乱码,这就表示这个自定义的网络创建成功了。

这个时候我们就可以使用 docker network ls 命令进行查看容器中的所有网络。

同时我们也可以使用 docker network inspect 命令查看我们所创建的网络信息。

[root@niuma ~]# docker network inspect niumanet
[
{
"Name": "niumanet",
"Id": "d8a7926fc04acc7123f520372472412c46969ae75e47d0104237840c919856cc",
"Created": "2023-01-08T15:28:15.952723923+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]

posted on   一颗蛋50斤  阅读(34)  评论(0编辑  收藏  举报

努力加载评论中...

导航

点击右上角即可分享
微信分享提示