Docker

本文最后更新于:2 分钟前

Docker 概述

Docker 为什么出现?

一款产品:开发–上线– 两套环境!应用环境,应用配置。

开发—–运维。问题:我在我的电脑上可以运行!版本更新,导致服务不可用,对于运维来说,考验十分大。

Docker 能干嘛

DevOps(开发、运维)

应用更快速的交付和部署

传统:一堆帮助文档,安装程序

Docker:打包镜像发布测试,一键运行

更便捷的升级和扩缩容

使用了Docker之后,我们部署应用就和搭积木一样简单

项目打包为一个镜像,扩展,镜像A,镜像B

更简单的系统运维

在容器化之后,我们的开发,测试环境都是高度一致的

更高效的计算资源利用

Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例!服务器的性能可以被压榨到极致。

Docker安装

Docker的基本组成

镜像(image):

docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,Tomcat镜像 —-> run ——> Tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

容器(container):

Docker 利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。

启动,停止,删除,基本命令!

目前就可以把这个容器理解为就是一个简易的Linux系统

仓库(repository):

仓库就是存放镜像的地方!

仓库分为共有仓库和私有仓库!

Docker Hub(默认是国外的)

阿里云…..都有容器服务器(配置镜像加速!)

安装Docker(基于CentOS7)

官方文档:https://docs.docker.com/

  1. 卸载旧的版本

    1
    2
    3
    4
    5
    6
    7
    8
    yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
  2. 安装需要的安装包

    1
    yum install -y yum-utils
  3. 设置镜像的仓库 默认是 国外的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

    # 推荐使用阿里云的镜像
    yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    #更新 yum软件包的索引
    yum makecache fast
  4. 安装docker docker-ce 社区版 ee 企业版

    1
    yum install docker-ce docker-ce-cli containerd.io
  5. 启动 docker

    1
    2
    3
    systemctl start docker
    # 使用 docker version 查看相关信息
    docker version
  6. hello world

    1
    docker run hello-world
  7. 查看一下这个下载的 hello world 镜像

    1
    2
    3
    4
    [root@jinan ~]# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    hello-world latest feb5d9fea6a5 6 weeks ago 13.3kB
    [root@jinan ~]#
  8. 了解 :卸载 docker

    1
    2
    3
    4
    5
    6
    7
    # 1、卸载依赖
    yum remove docker-ce docker-ce-cli containerd.io

    # 2、删除资源
    # /var/lib/docker docker 的默认工作路径
    rm -rf /var/lib/docker
    rm -rf /var/lib/containerd

阿里云镜像加速

  1. 登录阿里云 ,找到容器镜像服务

  2. 配置使用

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://u9mn54aq.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

回顾 Hello World 流程

底层原理

Docker 是怎么工作的?

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

DockerServer 接收到 Docker-Client 的指令,就会执行这个命令。

Docker 为什么比 VM快?

1、Docker有着比虚拟机更少的抽象层

2、Docker 利用的是 宿主机的内核。VM 需要的是 Guest OS

英文:

中文:

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

Docker的常用命令

帮助命令

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

帮助文档:https://docs.docker.com/reference/

镜像命令

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@jinan ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 6 weeks ago 13.3kB

# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小

#可选项
-a, --all # 列出所有镜像
-q, --quiet # 只显示镜像的 i

docker search 搜索镜像

1
2
3
4
5
6
7
8
9
10
11
[root@jinan ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11635 [OK]
mariadb MariaDB Server is a high performing open sou… 4429 [OK]


# 可选项,通过 收藏来过滤
-f STARS=5000 # 搜索出来的镜像就是 STARS大于5000的
[root@jinan ~]# docker search mysql -f STARS=5000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11635 [OK]

docker pull 下载镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 下载镜像  docker pull 镜像名[:tag]
[root@jinan ~]# docker pull mysql
Using default tag: latest # 如果不写 tag,默认就是 latest,最新的
latest: Pulling from library/mysql
b380bbd43752: Pull complete # 分层下载,docker image 的核心 联合 文件系统
f23cbf2ecc5d: Pull complete
30cfc6c29c0a: Pull complete
b38609286cbe: Pull complete
8211d9e66cd6: Pull complete
2313f9eeca4a: Pull complete
7eb487d00da0: Pull complete
4d7421c8152e: Pull complete
77f3d8811a28: Pull complete
cce755338cba: Pull complete
69b753046b9f: Pull complete
b2e64b0ab53c: Pull complete
Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址


# 等价于它
docker pull mysql
docker pull docker.io/library/mysql:latest

# 下载指定的版本
[root@jinan ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
b380bbd43752: Already exists
f23cbf2ecc5d: Already exists
30cfc6c29c0a: Already exists
b38609286cbe: Already exists
8211d9e66cd6: Already exists
2313f9eeca4a: Already exists
7eb487d00da0: Already exists
a71aacf913e7: Pull complete
393153c555df: Pull complete
06628e2290d7: Pull complete
ff2ab8dac9ac: Pull complete
Digest: sha256:2db8bfd2656b51ded5d938abcded8d32ec6181a9eae8dfc7ddf87a656ef97e97
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 删除镜像

1
2
3
4
5
6
# 删除指定的容器 
docker rmi -f 镜像id
# 删除多个容器
docker rmi -f 镜像id 镜像id 镜像id 镜像id
# 删除全部容器
docker rmi -f $(docker images -aq)

容器命令

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

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
docker run[可选参数] image

# 参数说明
--name="Name" 容器名字 Tomcat01 Tomcat02 ,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
-P 随机指定端口

# 测试,启动并进入容器
[root@jinan ~]# docker run -it centos /bin/bash
[root@21c66a321a57 /]#

# 查看容器内的 centos ,基础版本,很多命令不全
[root@5ad0ba439569 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var

# 从容器 退回主机
[root@21c66a321a57 /]# exit
exit

列出所有运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# docker ps 命令
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器 + 带出 历史运行过的容器
-n=? # 显示最近创建的容器
-p # 只显示容器的编号

[root@jinan /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

[root@jinan /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21c66a321a57 centos "/bin/bash" 3 minutes ago Exited (130) About a minute ago priceless_chaum
adfe59459fc2 feb5d9fea6a5 "/hello" 2 hours ago Exited (0) 2 hours ago heuristic_lederberg
[root@jinan /]#

[root@jinan ~]# docker ps -a -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5ad0ba439569 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago objective_ramanujan
[root@jinan ~]#

退出容器

1
2
exit  			#直接停止容器兵退出
Ctrl + P + Q #容器不停止退出

删除容器

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

启动和停止容器的操作

1
2
3
4
docker start 容器id		# 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止当前正在运行的容器

常用的其他命令

后台启动容器

1
2
3
4
5
6
7
# 命令  docker run -d 镜像名
[root@jinan ~]# docker run -d centos

# docker ps ,发现 centos 停止了。。。

# 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# Nginx:容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了

查看日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 命令  docker logs 容器id

# 参数: -t 时间 -f 跟踪


[root@jinan ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d061dbe1843a centos "/bin/bash" 8 seconds ago Exited (0) 5 seconds ago affectionate_tesla

[root@jinan ~]# docker logs -tf d061dbe1843a
2021-11-08T03:05:34.814534510Z [root@d061dbe1843a /]# exit
2021-11-08T03:05:34.814579620Z exit

# 只查一条 --tail 1
[root@jinan ~]# docker logs -tf --tail 1 d061dbe1843a
2021-11-08T03:05:34.814579620Z exit
[root@jinan ~]#

查看容器中进程信息

1
2
3
4
5
6
# 命令 docker top 容器id

[root@jinan ~]# docker top 462a33b2341d
UID PID PPID C STIME TTY TIME CMD
root 25972 25954 0 11:15 pts/0 00:00:00 /bin/bash

查看镜像的元数据

1
# 命令 docker inspect 容器id

进入当前正在运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些设置

# 命令 docker exec -it 容器id bash
[root@jinan ~]# docker exec -it 462a33b2341d bash
[root@462a33b2341d /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@462a33b2341d /]#

# 方式二 docker attach 容器id
[root@jinan ~]# docker attach 462a33b2341d
正在执行当前的代码

# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入容器正在执行的 终端,不会启动新的进程!

从容器拷贝到主机上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#命令 docker cp 容器id

# 测试
# 查看当前主机目录下
[root@jinan home]# ls
jinan redis test222 test.java www

[root@jinan home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
462a33b2341d centos "/bin/bash" 25 minutes ago Up 43 seconds hardcore_golick

# 进入 容器
[root@jinan home]# docker attach 462a33b2341d
[root@462a33b2341d /]# cd /home
[root@462a33b2341d home]# ls
test.java
# 在容器内新建一个文件
[root@462a33b2341d home]# touch jinan.txt
[root@462a33b2341d home]# exit
exit

# 将这个文件拷贝到主机上
[root@jinan home]# docker cp 462a33b2341d:/home/jinan.txt /home
[root@jinan home]# ls
jinan jinan.txt redis test222 test.java www
[root@jinan home]#

# 拷贝是一个手动过程,未来可以使用 -v 卷的技术,可以实现

小结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
attach 	Attach to a running container 		#当前she11 下attach 连接指定运行镜像
build Build an image from a Dockerfile #通过Dockerfile定制诡像
commit create a new image from a container changes #提交当前容器为新的镜像cp
copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container #创建一个新的容器,同run,但不启动容器
diff Inspect changes on a container‘s filesystem #查看docker容器变化
eventsGet real time events from the server #从docker服务获取容器实时事件
exec Run a command in an existing container #在已存在的容器上运行命令
export Stream the contents of a container as a tar archive #导出容器的内容流作为一个 tar归档文件[对应import ]
history show the history of an image #展示一个镜像形成历史
images List images #列出系统当前镜像
import create a new filesystem image from the contents of a tarball #从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information #显示系统相关信息
inspect Return low-level information on a container #查看容器详细信息
ki11ki1l a running container #ki11指定docker容器
loadLoad an image from a tar archive #从一个tar包中加载一个镜像[对应save]
login Register or Login to the docker registry server#注册或者登陆一个docker 源服务器
logoutLog out from a Docker registry server #从当前Docker registry退出
logsFetch the logs of a container #输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRTVATE_PORT#查看映射端口对应的容器内部源端口
pausePause a11 processes within a container #暂停容器
ps List containers #列出容器列表
pull pull an image or a repository from the docker registry server# 从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to the docker registry server#推送指定镜像或者库镜像至docker源服务器
restart Restart a running container #重启运行的容器
rm Remove one or more containers #移除一个或者多个容器
rmi Remove one or more images #移除一个或多个镜像[无容器使用该镜像才可刷除,否则需删除相关容器才可继续或-f强制删除]
run Run a command in a new container #创建一个新的容器并运行一个命令
save save an image to a tar archive #保存一个镜像为一个tar包[对应1oad]
search search for an image on the Docker Hub #在docker hub中搜索镜像
start start a stopped containers #启动容器
stop Stop a running containers #停止容器
tag Tag an image into a repository #给源中镜像打标签
top Lookup the running processes of a container #查看容器中运行的进程信息
unpause Unpause a paused container #取消暂停容器
version show the docker version information #查看docker版本号
wait Block until a container stops,then print its exit code#截取容器停止时的退出状态值

部署Nginx

1、搜索镜像

1
docker search nginx

2、下载镜像

1
docker pull nginx

3、启动镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 以后台方式启动,命名nginx01  通过公网的8077 端口访问docker中的80端口
# -d 后台启动 --name 命名 -p 宿主机端口:容器内部端口
[root@jinan home]# docker run -d --name nginx01 -p 8077:80 nginx
e784a1581f9418de503f3ff0d2082e7c3e11760300bd19d72c6014128eafb856
[root@jinan home]#

# 进入容器
[root@jinan ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e784a1581f94 nginx "/docker-entrypoint.…" 13 minutes ago Up 13 minutes 0.0.0.0:8077->80/tcp nginx01
[root@jinan ~]# docker exec -it nginx01 bash
root@e784a1581f94:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@e784a1581f94:/# cd /etc/nginx
root@e784a1581f94:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
root@e784a1581f94:/etc/nginx#

端口暴露的概念

部署 Tomcat

Docker Hub链接:https://hub.docker.com/_/tomcat

1
2
3
# 官方的使用
docker run -it --rm tomcat:9.0docker exec -it tomcat01 bash
# 一般用来测试 ,用完即删

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 下载
docker pull tomcat:9.0
# 启动
docker run -d -p 8077:8080 --name tomcat01 tomcat

# 测试访问没有问题

# 进入容器
docker exec -it tomcat01 bash

# 发现问题
# 1、Linux命令少了 2、没有webapps。阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉
# 保证最小的可运行的环境

可以使用
cp -r webapps.dist/* webapps

部署 ES + Kibana

暂无,以后看了ES之后在搞

可视化

  • portainer
  • Rancher

什么是 portainer?

Docker的图形化管理工具,提供一个后台面板提供我们操作

1
2
docker run -d -p 8077:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

通过 http://ip:8077/ 访问

首先是一个登录界面

然后登录完之后选择本地的

控制面板

Docker镜像

镜像是很什么

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

所有的应用,直接打包docker镜像,就可以直接跑起来!如何得到镜像:

  • 从远程仓库下载
  • 朋友拷贝给你
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFS (联合文件系统)

UnionFS ( 联合文件系统):Union文件系统( UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。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, letc等标准目录和文件。roots就是各种不同的操作系统发行版,比如Ubuntu ,Centos等等。

平时我们安进虚拟机的 Centos 都是好几个G,为什么Docker才 200M

1
2
3
[root@jinan ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 5d0da3dc9764 7 weeks ago 231MB

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

虚拟机是分钟级别,容器是秒级

Commit镜像

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

docker commit -m "提交的描述信息" -a "作者" 容器id 目标镜像名:[TAG]

实战测试

1
2
3
4
5
6
7
# 1、启动一个默认的tomcat

# 2、发现这个默认的Tomcat 是没有默认的webapps 应用,镜像的原因,官方的镜像默认 webapps 下是没有文件的

# 3、拷贝进去基本的文件

# 4、将操作过的容器通过 commit 提交为一个镜像,以后使用这个镜像即可,这就是自己修改的一个镜像
1
2
3
4
5
6
7
8
9
10
[root@jinan ~]# docker commit -a="jinan" -m="add webapps" 63307da8b765 tomcatplus:1.0
sha256:5651fa24257eff9895e762d8167e6b8014e24532eb0a2857e10f5809d8ea7c64
[root@jinan ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcatplus 1.0 5651fa24257e 7 seconds ago 685MB
tomcat 9.0 43e421a14aec 2 weeks ago 680MB
nginx latest 87a94228f133 3 weeks ago 133MB
centos latest 5d0da3dc9764 7 weeks ago 231MB
portainer/portainer latest 580c0e4e98b0 7 months ago 79.1MB
[root@jinan ~]#

学习方式:理解概念,但是一定要实践,最后实践和理论相结合一次搞定

1
如果要保存当前容器的状态,就可以通过commit来提交,获得一个镜像

容器数据卷

什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像。

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化

MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地。

这就是卷技术,目录的挂载,将我们容器内的目录,挂载到Linux上面。

总结一句话:容器的持久化和同步操作,容器间也是可以数据共享的

使用数据卷

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

1
2
3
4
5
6
docker run -it -v 主机目录:容器内目录

# 测试
[root@jinan home]# docker run -it -v /home/ceshi:/home centos bash

#启动起来可以通过 docker inspect 容器id 查看是否挂载成功

测试文件的同步

再次测试

1、停止容器

2、在宿主机上修改文件

3、启动容器

4、容器中的数据依旧是同步的

好处:以后修改只需要在本地修改即可,容器内会自动同步

实战:安装MySQL

思考:MySQL 的数据持久化问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 获取镜像
[root@jinan home]# docker pull mysql:5.7

# 运行容器 ,需要做数据挂载

# 官方测试 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 启动我们的
-d 后台运行
-p 端口映射
-v 卷瓜子啊
-e 环境配置
--name 容器名字
[root@jinan home]# docker run -d -p 8077:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=jinanc --name mysql01 mysql:5.7

# 启动成功之后,可以在本地使用 数据库管理工具 连接测试

# 在本地测试创建一个数据库,查看一下映射的路径是否ok

假设我们将容器删除,发现,挂载到本地的数据卷依旧存在,就会实现了容器数据持久化

具名挂载和匿名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看所有的 volume 的情况
[root@jinan home]# docker volume ls
DRIVER VOLUME NAME
local c4ac0d282a0c9981e7334079182a379d0b9d41bee0e9f1ffb2f9603051f59840

# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径


# 具名挂载
[root@jinan home]# docker run -d -p 8077:80 -v juming:/etc/nginx nginx
3d489f3ed36df65a546eed2d1e2b04a92e4443605a9c8dba702284e001a433f7
[root@jinan home]# docker volume ls
DRIVER VOLUME NAME
local juming


# 通过 -v 卷名:容器内路径
# 查看一下这个卷

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/

我们可以通过具名挂载 可以方便的找到我们的一个卷,大多数情况使用具名挂载

1
2
3
4
5
# 如何确定是 具名挂载还是匿名挂载 ,还是指定路径挂载

-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载

扩展:

1
2
3
4
5
6
7
8
9
10
# 通过 -v 容器内路径: ro rw 改变读写权限

ro readonly # 只读
rw readwrite # 可读可写

# 一但这个设置了容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -p 8077:80 -v juming:/etc/nginx:ro nginx
docker run -d -p 8077:80 -v juming:/etc/nginx:rw nginx

# ro 只要看到 ro 就说明这个路径只能通过宿主机来操作,容器内部是无法操作的

初识DockerFile

DockerFile 就是用来构建docker 镜像的构建文件!命令脚本

通过这个脚本,可以生成一个镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层

1
2
3
4
5
6
7
8
9
10
11
# 创建一个 dockerfile文件,名字可以随机,建议 Dockerfile
# 文件中的内容 指令(大写) 参数

FROM centos

VOLUME ["volume01","volume02"]

CMD echo "----end-----"
CMD /bin/bash

# 这里的每个命令,就是镜像的一层

这个卷和外部一定有一个同步的目录,匿名挂载

查看卷 挂载的路径

这种未来使用的十分多,因为我们通常会构建自己的镜像!

假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!

数据卷容器

多个MySQL同步数据!

1
# 启动3个容器,通过刚才自己写的镜像启动

启动 第二个容器

1
2
# 测试,可以删除docker01,查看一下docker02 和docker03 是否还可以访问这几个文件
# 依旧可以访问

结论:

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

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

DockerFile

DockerFile介绍

dockerfile 是用来构建docker镜像的文件,命令参数搅拌

构建步骤:

1、编写一个 dockerfile 文件

2、docker build 构建成为一个镜像

3、docker run 运行镜像

4、docker push 发布镜像(DockerHub,阿里云镜像仓库)

查看一下官方是怎么做的?

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,我们自己也可以

DockerFile 构建过程

基础知识:

1、每个保留关键字(指令)都必须是大写字母

2、执行从上到下的顺序执行

3、# 表示注释

3、每一个指令都会创建提交一个新的镜像层,并提交

dockerfile 是面向开发的,我们以后要发布羡慕,做镜像,就需要编写dockerfile文件,这个文件十分简单

Docker镜像 逐渐成为了企业交付的标准,必须要掌握

步骤:开发,部署,运维。。。

DockerFile:构建文件,定义了一切的步骤,源代码

DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行的产品

Docker容器:容器就是镜像运行起来提供服务器

DockerFile的指令

1
2
3
4
5
6
7
8
9
10
11
12
 FROM  			# 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 株洲,Tomcat镜像,这个Tomcat压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CND # 指定这个容器启动的时候要运行的命令,只有最后一个生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似 ADD 将我们的文件拷贝到镜像中国
ENV # 构建的时候设置环境变量

实战测试

Docker Hub中 99%的镜像都是从这个基础镜像过来的,然后配置需要的软件和配置来进行的构建

FROM scratch

创建一个自己的centos

1、编写 dockerfile 的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM centos
MAINTAINER jinan<2640053707@qq.com>

EVN MYPATH /usr/local
WORKIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "-----end-----"
CMD /bin/bash

2、通过这个文件 构建镜像

1
2
3
4
5
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]

Successfully built a8bac4f3356d
Successfully tagged mycentos:0.1
# 出现 Successfully 即为成功

3、测试运行

对比:之前原生的centos

我们增加之后的镜像

我们可以列出本地镜像的变更历史

1
docker history 镜像id

实战:Tomcat镜像

1、准备镜像文件 Tomcat 压缩包 ,jdk 的压缩包

2、编写 dockerfile 文件,官方命名 Dockerfile,build会自动寻找这个文件,就不需要 -f 指定了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
FROM centos
MAINTAINER jinan<2640053707@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u202-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.54.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_202
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.54
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin


EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.54/bin/logs/catalina.out

3、构建镜像

1
# docker build -t diytomcat .

4、启动镜像

1
docker run -d -p 8077:8080 --name jinantomcat -v /home/jinan-docker/tomcat/test:/usr/local/apache-tomcat-9.0.54/webapps/test -v /home/jinan-docker/tomcattomcatlogs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat

5、访问测试

http://39.106.0.220:8077/

6、发布项目(由于做了卷挂载,直接在本地编写项目就可以发布了)

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>

<h1>Hello World</h1>
<p>测试 docker 中 的Tomcat</p>

</body>
</html>

访问:http://39.106.0.220:8077/test/

发布自己的镜像

Docker Hub

1、注册一个账号

2、确定这个账号可以登录

3、在我们的服务器上提交自己的镜像

1
2
3
4
5
6
7
8
9
10
11
12
[root@jinan test]# docker login --help

Usage: docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
[root@jinan test]#

登录账号

1
2
3
4
5
6
7
8
[root@jinan test]# docker login -u jinan6
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@jinan test]#

登录完成之后 docker push 命令发布镜像

问题:发布时,提示镜像不存在,拒绝push等情况

1
2
3
4
The push refers to repository [docker.io/jinan/diytomcat]
An image does not exist locally with the tag: jinan/diytomcat

denied: requested access to the resource is denied

解决:

1
2
3
# 先执行 docker tag 镜像名  DockerHub用户名/镜像名:版本号
# 在执行 push 命令
# docker push DockerHub用户名/镜像名:版本号

发布到阿里云

暂无,有需要可以看文档:https://cr.console.aliyun.com/cn-hangzhou/new

小结

Docker网络

docker0

清空所有环境

测试

三个网络

1
# 问题 docker 是如何处理容器网络访问的?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 运行Tomcat
docker run -d -p 8077:8080 --name tomcat01 tomcat

# 查看对应端口,这个命令不行,,
docker attach -it tomcat01 i ip addr
# 解决 进入 Tomcat 容器 ,执行 apt-get update,apt-get install -net-tools,然后可以使用 ifconfig查询
[root@jinan ~]# docker exec -it tomcat01 ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 5258 bytes 9073434 (8.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5203 bytes 362114 (353.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0


# 列出所有容器的IP地址
[root@jinan ~]# docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
/tomcat01 - 172.17.0.2

思考:Linux 能不能 ping 通 容器内部?

1
2
3
4
5
# 可以!
[root@jinan ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.069 ms

原理

我们每启动一个 docker 容器,docker 就会给docker容器分配一个ip。我们只要安装了docker,就会有有一个网卡 docker0

桥接模式,使用的是 veth-pair 技术

veth-pair技术

1
2
3
# 就是一对虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,veth-pair 充当一个桥梁,连接各种虚拟网络设备
# OpenStac, Docker容器之间的连接,OVS的连接,都是使用 veth-pair 技术

容器和容器之间也是可以相互 ping 通的

结论:tomcat01 和 tomcat02 是公用的一个路由器,docker0。

所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用IP

小结

Docker 使用的是 Linux的桥接,宿主机中是一个 Docker 容器的网桥 docker0。

Docker 中的所有网络接口都是虚拟的,虚拟的转发效率高

只要容器停止或删除,对应的网桥就会消失

–link

现在不用了

自定义网络

查看所有的 docker 网络

1
2
3
4
5
[root@jinan ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
aa9b860284dd bridge bridge local
3a264c67de20 host host local
52b4382173d1 none null local

网络模式

bridge:桥接 docker(默认自己创建也使用桥接模式)

none:不配置网络

host:和宿主机共享网络

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 我们直接启动的命令  --net bridge,而这个就是我们的docker0
docker run -d -P tomcat01 tomcat
docker run -d -P tomcat01 --net brige tomcat

# docker0 的特点:默认,ip不能访问,--link可以打通连接

# 自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@jinan ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
24bf902d70d6ebb16d43c94a557b4a7d488d3ad17c54169ede8f1b68a43186f6
[root@jinan ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
aa9b860284dd bridge bridge local
3a264c67de20 host host local
24bf902d70d6 mynet bridge local
52b4382173d1 none null local
[root@jinan ~]#

自定义网络 docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络

好处:

redis:不同的集群使用不同的网络,保证集群是安全和健康的

mysql:不同的集群使用不同的网络,保证集群是安全的和健康的

网络连通

忽略了

发布一个SpringBoot试试

1、构建springboot项目

2、打包应用

3、编写 dockerfile

4、构建镜像

5、发布运行


本文作者: 仅安
本文链接: https://jinan6.vip/posts/4126800539/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!