面试题之Docker狂神学习笔记

Docker解密
Docker 平台的基本构成

安装Docker
环境准备
1、需要会一点点Linux基础
2、CentOS 7
3、Xshell 或者其它远程连接工具
环境查看
# 查看系统内核, 要求版本>3.10
uname -r
3.10.0-1062.12.1.el7.x86_64
# 查看系统版本等相关信息
cat /etc/os-release
安装
帮助文档:
# 1. 卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-engine
# 2. 安装依赖包
yum install -y yum-untils
# 3. 设置镜像仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo # 默认国外的镜像仓库
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里云的镜像仓库(推荐)
# 更新yum软件包索引
yum makecache fast
# 4. 安装Docker相关, docker-ce 社区版 docker-ee 企业版
yum install docker-ce docker-ce-cli containerd.io
# 安装指定版本
yum install docker-ce-<VERSION-STRING> docker-ce-cli-<VERSION-STRING> container.io
# 5. 启动Docker
systemctl start docker
# 6. 使用docker version查看是否安装成功
docker version
# 7. 测试 HelloWorld!
docker run hello-world
# 8. 查看已下载的镜像
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 5 months ago 13.3kB
卸载docker
# 1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2. 删除资源
rm -rf /var/lib/docker # Docker的默认工作资源路径
安装-2
RedHat/CentOS必须要6.6版本以上,或者7.x才能安装docker,建议在RedHat/CentOS 7上使用docker,因为RedHat/CentOS 7的内核升级到了kernel 3.10,对lxc容器支持更好。
查看Linux内核版本(内核版本必须是3.10或者以上):
cat /proc/version
uname -a
lsb_release -a
# 无法执行命令安装
yum install -y redhat-lsb
更新YUM源:
yum update
安装:
yum install docker -y
检查版本:
docker -v
安装完成后,使用下面的命令来启动 docker 服务,并将其设置为开机启动:
service docker start
chkconfig docker on
阿里云镜像加速
- 登陆阿里云, 找到"容器镜像服务"
- 找到"镜像加速器"
- 配置使用
- 重启Docker服务
docker run 的运行流程
底层原理
Docker是怎么工作的?
Docker 是一个 Client-Server 结构的系统, Docker的守护进程运行在主机上. 通过Socket从客户端访问!
DockerServer 接收到 Docker-Client 的指令, 就会执行这个命令!
Docker 为什么比 VM 快?
- Docker 有着比虚拟机更少的抽象层
- Docker 利用的是宿主机的内核, VM 需要的是Guest OS
所以说, 新建一个容器的时候, docker不需要像虚拟机一样重新家在一个操作系统内核, 避免隐刀. 虚拟机是加载Guest OS , 分钟级别的. 而Docker 是利用宿主机的操作系统, 省略了这个复杂的过程, 秒级!
Docker 的常用命令
帮助命令
docker verion # 显示 docker 的版本信息
docker info # 显示 docker 的系统信息, 包括镜像和容器的数量等
docker COMMAND --help # 帮助命令
帮助文档的地址:Reference documentation | Docker Documentation
镜像命令
docker imagesdocker image | Docker Documentation
[root@Oskari docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos 7 8652b9f0cb4c 8 months ago 204 MB
# 解释
REPOSITORY # 镜像的仓库员
TAG # 镜像的标签
IMAGE ID # 镜像的id
CREATED # 镜像的创建时间
SIZE # 镜像的大小
# 可选项
-a # 列出所有镜像
-q # 指向是镜像的id
docker search 搜索镜像docker search | Docker Documentation
[root@Oskari docker]# docker search mysql
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/mysql MySQL is a widely used, open-source relati... 11205 [OK]
docker.io docker.io/mariadb MariaDB Server is a high performing open s... 4259 [OK]
docker.io docker.io/mysql/mysql-server Optimized MySQL Server Docker images. Crea... 833 [OK]
docker.io docker.io/percona Percona Server is a fork of the MySQL rela... 548 [OK]
docker.io docker.io/phpmyadmin phpMyAdmin - A web interface for MySQL and... 286 [OK]
# 可选项
Name, shorthand Default Description
--filter , -f Filter output based on conditions provided
--format Pretty-print search using a Go template
--limit 25 Max number of search results
--no-trunc Don't truncate output
# 通过收藏数量过滤
--filter=STARS=3000 # 搜索STARS数量大于3000的
[root@Oskari docker]# docker search mysql -f=stars=3000
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/mysql MySQL is a widely used, open-source relati... 11205
docker.io docker.io/mariadb MariaDB Server is a high performing open s... 4259
docker pull 拉取镜像docker pull | Docker Documentation
# 下载镜像 docker pull IMAGENAME[:tag]
[root@Oskari docker]# docker pull mysql
Using default tag: latest # 如果不写 tag , 默认拉取最新版本
Trying to pull repository docker.io/library/mysql ...
latest: Pulling from docker.io/library/mysql
33847f680f63: Pull complete # 分层下载, docker image 核心 [联合文件系统]
5cb67864e624: Pull complete
1a2b594783f5: Pull complete
b30e406dd925: Pull complete
48901e306e4c: Pull complete
603d2b7147fd: Pull complete
802aa684c1c4: Pull complete
715d3c143a06: Pull complete
6978e1b7a511: Pull complete
f0d78b0ac1be: Pull complete
35a94d251ed1: Pull complete
36f75719b1a9: Pull complete
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd # 签名
Status: Downloaded newer image for docker.io/mysql:latest # 真实地址
# 下面两条命令是一样的涵义
docker pull mysql
docker pull docker.io/mysql:latest
# 指定版本下载
[root@Oskari docker]# docker pull mysql:5.7
Trying to pull repository docker.io/library/mysql ...
5.7: Pulling from docker.io/library/mysql
33847f680f63: Already exists # 核心文件共用
5cb67864e624: Already exists
1a2b594783f5: Already exists
b30e406dd925: Already exists
48901e306e4c: Already exists
603d2b7147fd: Already exists
802aa684c1c4: Already exists
5b5a19178915: Pull complete
f9ce7411c6e4: Pull complete
f51f6977d9b2: Pull complete
aeb6b16ce012: Pull complete
Digest: sha256:be70d18aedc37927293e7947c8de41ae6490ecd4c79df1db40d1b5b5af7d9596
Status: Downloaded newer image for docker.io/mysql:5.7
[root@Oskari docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mysql 5.7 8cf625070931 12 days ago 448 MB
docker.io/mysql latest c60d96bd2b77 12 days ago 514 MB
docker.io/centos 7 8652b9f0cb4c 8 months ago 204 MB
docker rmi 删除镜像
docker rmi IMAGENAME / IMAGE ID
# 批量删除
docker rmi -f $(docker images -aq) # 查出所有镜像id, 递归删除
容器命令
下载一个CentOS镜像来测试学习
docker pull centos
新建容器并启动
docker run [ARGS] IMAGENAME
# 参数说明
--name="NAME" # 容器别称, 用来区分不同容器
-d # 后来方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
# 测试 启动并进入容器
[root@Oskari docker]# docker run -it centos:7 /bin/bash
[root@1df2f1c76ad1 /]# ls # 查看容器内的centos, 基础版本, 很多命令都不是完善的.
# 从容器中退出主机
[root@1df2f1c76ad1 /]# exit
[root@Oskari docker]
列出所有的运行的容器
# docker ps 列出正在运行的容器
# docker ps -a 列出当前正在运行的容器+历史运行过的容器
# docker ps -n=? 显示最近创建的容器 ? number 指个数
# docker ps -q 只显示容器的编号
[root@Oskari docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@Oskari docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1df2f1c76ad1 centos:7 "/bin/bash" 18 minutes ago Exited (0) 8 seconds ago agitated_heyrovsky
[root@Oskari docker]#
退出容器
exit # 停止容器并退出
Ctrl+P+Q # 保持容器运行并退出
删除容器
docker rm 容器id # 删除单个容器
docker rm 容器id 容器id # 删除多个容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -aq|xargs docker rm # 删除所有容器
启动和停止容器的操作
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止当前正在运行的容器
docker kill 容器id # 强制停止容器
常用其它命令
后台启动容器
# 命令 docker run -d IMAGENAME
[root@Oskari docker]# docker run -d centos
# 问题: docker ps 发现 centos 停止了
# 常见的坑: docker 容器使用后台运行, 就必须要有一个前台进程. docker发现没有应用, 就会自动停止
查看日志
# docker logs
[root@Oskari docker]# 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
--help Print usage
--since string Show logs since timestamp
--tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
[root@Oskari docker]# docker logs -tf --tail 10 CONTAINER-ID # 查看某容器最后10条日志
查看容器中的进程信息
docker top CONTAINERID # 查看运行中的容器的进程
查看镜像的元数据
docker inspect containerid
进入当前正在运行的容器
# 容器通常设定为后台运行. 如果有进入容器的需要
[root@Oskari docker]# docker exec -it 25d00508c3f9 /bin/bash # 通过exec进入容器, 并创建一个 /bin/bash 进程
[root@Oskari docker]# docker attach 25d00508c3f9 # 通过attach进入容器, 进入正在运行的进程, 并不会创建进程
容器内拷贝文件到宿主机上
# docker cp
# 进入容器, 创建要拷贝的文件
[root@Oskari docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef0508f169f9 centos:7 "/bin/bash" 2 minutes ago Up 2 minutes tender_darwin
[root@Oskari docker]# docker attach ef0508f169f9
[root@ef0508f169f9 home]# ls
test.txt
[root@ef0508f169f9 home]# exit
# 退出容器, 进入宿主机, 可以不在意容器运行状态, 只要容器存在即可
[root@Oskari home]# pwd
/home
[root@Oskari home]# docker cp ef0508f169f9:/home/test.txt /home
[root@Oskari home]# ls
test.txt
[root@Oskari home]# cat test.txt
test file from ef0508f169f9
[root@Oskari home]#
# docker cp containerid:/path /path
# 拷贝是一个手动过程, 未来我们可以使用 -v 卷的技术, 做到数据自动同步
作业练习
Docker 安装 Nginx
搜索镜像
[root@Oskari home]# docker search nginx
拉取镜像
[root@Oskari home]# docker pull nginx
后台方式启动Nginx镜像并重命名
[root@Oskari home]# docker run -d --name nginx01 -p 3344:80 nginx # 3344为宿主机端口,80为容器内部端口
0095b1e54ed30f6b71da17e6e975fe4af7982b58ec6b6b5c1efe19618a374f7d
[root@Oskari home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0095b1e54ed3 nginx "/docker-entrypoin..." 4 seconds ago Up 2 seconds 0.0.0.0:3344->80/tcp nginx01
端口暴露概念

测试环境安装结果
[root@Oskari home]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@Oskari home]#
问题: 每次改动nginx配置文件, 都需要进入容器内部, 是分麻烦. 如果可以在容器外部提供一个映射路径, 达到在容器外部修改文件, 容器内部就可以自动修改? TIPS: -v 挂载卷
使用 Docker 安装一个 Tomcat
# 官方推荐命令 , 携带版本
docker run -it --rm tomcat:9.0 # 指定下载9.0版本
# 我们之前的启动都是后台, 停止容器之后, 容器还是可以查到. --rm 在容器停止后会删除该镜像
启用一个新的tomcat容器, 别名 tomcat01, 宿主机使用3355映射容器的8080端口
docker run -d -p 3355:8080 --name tomcat01 tomcat
这里在宿主机中使用curl命令会发现 HTTP STAUS 404 , 原因: Tomcat 镜像为阉割版本
[root@Oskari home]# docker exec -it tomcat01 /bin/bash
root@8bbdd54e1ca5:/usr/local/tomcat#
# 发现问题 1. linux 命令少了, ll 无法使用. 2. webapps 文件夹空. 3. 阿里云镜像的原因,默认是最小的镜像,剔除不必要的所有文件, 保证最小可运行环境
[root@Oskari home]# docker exec -it tomcat01 /bin/bash
root@8bbdd54e1ca5:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@8bbdd54e1ca5:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@8bbdd54e1ca5:/usr/local/tomcat# ls webapps
ROOT docs examples host-manager manager
root@8bbdd54e1ca5:/usr/local/tomcat#
思考问题: 以后部署项目流程中, 每次都需要进入容器调整配置文件, 过于麻烦, 如何解决? TIPS: -v 挂载卷
部署 es + kibana
# es 暴露端口较多
# es 占用内存较多
# es 需要将数据放置到安全目录! 挂载
# 安装镜像,启动容器
[root@Oskari home]# docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# docker stats 查看 docker 内核运行状态
# 测试es是否安装成功
[root@Oskari home]# curl localhost:9200
{
"name" : "0a772db1fcba",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "pFUYgLbEQWOUeVEdShsplQ",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
[root@Oskari home]#
# 增加 es 内存限制 -e 环境配置修改
[root@Oskari home]# docker run -d --name es02 -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms64m -Xmx512m" -e "discovery.type=single-node" elasticsearch:7.6.2

使用 kibana 链接 es

可视化管理
- portainer (先用这个)
[root@Oskari home]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher (CI/CD再用)
什么是 portainer ?
Docker 图形化界面管理工具! 提供一个后台面板供我们操作!
[root@Oskari home]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Docker 镜像讲解
Commit 镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 启动一个默认的tomcat镜像, webapps里兵没有应用(镜像原因), 将webapps.list 下的所有文件移动至webapps文件夹下
# 将更改后的容器通过commit提交成为一个新的奖项.
[root@Oskari ~]# docker commit -a="oskari" -m="reset webapps files" 8bbdd54e1ca5 tomcat_normal:1.0
sha256:5e03b52c61624e583666cada38f58fb33e32b72ba17fe2e99b8bf1fdd6919b09
[root@Oskari ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat_normal 1.0 5e03b52c6162 4 seconds ago 673 MB
docker.io/tomcat 9.0 46cfbf1293b1 13 days ago 668 MB
如果想要保存当前容器的状态, 就可以通过 commit 来提交, 获取一个镜像. 就像VM的快照一样!
容器数据卷
什么是容器数据卷?
docker的理念
将应用和环境打包成一个镜像! 数据如果都存储在容器中, 如果容器被删除, 数据随之丢失. 故: 数据需要持久化. 通过容器之间数据共享技术, Docker容器中产生的数据同步到本地宿主机.
这就是卷技术! 目录的挂载, 将我们容器内的目录, 挂载到宿主机上!
总结: 容器的持久化和同步操作, 多个容器之间也是可以数据共享的!
使用数据卷
方式一: 直接使用命令 -v 进行数据地址挂载
docker run -it -v 宿主机目录:容器目录 IMAGENAME
测试一:
# 测试
[root@Oskari home]# docker run -it -v /home/test:/home centos:7 /bin/bash
# 查看卷是否挂载成功
[root@Oskari home]# docker inspect 3fe744aed21c
"Mounts": [ # 挂载
{
"Type": "bind",
"Source": "/home/test", # 宿主机位置
"Destination": "/home", # 容器内的位置
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
# 双向绑定
# 宿主机创建文件同步至容器
[root@Oskari test]# touch test.txt
[root@Oskari test]# docker attach 3fe744aed21c
[root@3fe744aed21c home]# ls
test.txt
[root@3fe744aed21c home]#
# 容器内创建文件同步至宿主机
[root@3fe744aed21c home]# touch test_from_container.txt
# 退回至宿主机
[root@Oskari test]# ls
test_from_container.txt test.txt
测试二:
# 在宿主机更改test.txt文件内容, 添加"This is update from Linux!"
# 在容器中查看文件内容, cat test.txt, 获取文字 "This is update from Linux!"
# 在容器冲更改test_from_container.txt 文件内容, 添加"This is update from Container!"
# 在宿主机中查看文件内容, cat test_from_container.txt, 获取文字 "This is update from Container!"
安装MySQL(持久化数据)
思考: MySQL的数据持久化的问题
以MySQL5.7为示例
启动MySQL5.7镜像, 创建容器, -p 端口映射, -v 挂载
# 启动镜像, 做配置文件以及数据挂载
# 注意: 安装启动MySQL要配置ROOT密码!!!
# Offical: docker run --name some-mysql -e MY_ROOT_PASSWD=PASSWD -d mysql:tag
# -d 后台运行
#-p 端口映射
# -v 数据卷挂载
# -e 环境配置
# --name 容器名字
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123123 --name mysql01 mysql:5.7
具名挂载和匿名挂载
# 匿名挂载
-P 大写的P, 映射随机端口
-v 容器内路径
docker run -d -P --name nginx02 -v /etc/nginx nginx
# 查看数据卷的相关帮助命令
docker volume --help
Options:
--help Print usage
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused volumes
rm Remove one or more volumes
# 查看所有数据卷信息
docker volume ls
DRIVER VOLUME NAME
local 62c9d09e0c0693635857ea94246534747a7276950e1bd75f79260d25d2e9407e
local dc0cc8aaee37ac6d0d9d68e4d7f08b26fe6867a3df396d29a62e119af7cfd121
# VOLUME NAME 当前显示为匿名数据卷, 在 -v 挂载的时候只写了容器内的路径,没有写宿主机的路径
# 具名挂载
# 通过 -v 卷名:容器内路径
docker run -d -P --name nginx03 -v juming-nginx:/etc/nginx nginx
所有Docker容器内的数据卷, 在没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data 路径下.
我们通过具名挂载可以方便地找到我们需要查询的数据卷. 大多数情况都是在使用 具名挂载
# 如何确定是具名挂载还是匿名挂载, 亦或是指定路径挂载?
-v 容器内路径 # 匿名挂载
-v 数据卷名:/容器内路径 # 具名挂载
-v /宿主机路径:/容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径: ro rw 改变读写权限
# ro readonly 只读
# rw readwrite 读写
# 如果设置了容器权限, 容器对挂载出来的数据就有权限限定了.
docker run -d -P --name nginx04 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx04 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作, 容器内部是无法操作
初识Dockerfile
Dockerfile 就是用来构建 docker 镜像的构建文件的命令脚本
通过脚本生成镜像, 镜像是一层一层的. 脚本就是一个一个的命令, 每个命令都是一层.
创建 dockerfile1 文件
ROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----VOLUME END-----"
CMD /bin/bash
执行构建镜像命令
docker build -f ./dockerfile1 -t oskari/centos:1.0 .
启动刚刚构建的镜像运行一个容器
这两个数据卷是在dockerfile1中挂载的(匿名挂载). 所以宿主机一定有一个与之同步的目录
查看数据卷挂载路径
# 进入容器,在挂载的数据卷 volume01 中创建测试文件container.txt文件
# 宿主机中查看容器源数据, 找到挂载信息
docker inspect c0fe3ce4ec96
"Mounts": [
{
"Type": "volume",
"Name": "a77fa64e6c71513d905f7307ad44df496dfcba948288113162dbf5ab036b317e",
"Source": "/var/lib/docker/volumes/a77fa64e6c71513d905f7307ad44df496dfcba948288113162dbf5ab036b317e/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "d0c1bb2ca01b0e4c38d0cc3b0d3e632c8440fd98ea49811243a4283a86a77f55",
"Source": "/var/lib/docker/volumes/d0c1bb2ca01b0e4c38d0cc3b0d3e632c8440fd98ea49811243a4283a86a77f55/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
进入宿主机目录
cd /var/lib/docker/volumes/a77fa64e6c71513d905f7307ad44df496dfcba948288113162dbf5ab036b317e/_data
我们就能够看到刚刚创建的 container.txt 文件.( 当然, 你需要执行 ls 命令 )
数据卷容器
多个容器间同步
# 通过我们刚刚自己生成的镜像来启动一个容器
docker run -it -d --name docker01 oskari/centos:1.0 # 作为父容器
创建 docker02
# 创建docker02
docker run -it --name docker02 --volumes-from docker01 oskari/centos:1.0
进入 docker01 创建测试同步文档
[root@4cf79574d316 /]# docker attach docker01
[root@4cf79574d316 /]# cd volume01
[root@4cf79574d316 volume01]# ls
[root@4cf79574d316 volume01]# touch docker01.txt
[root@4cf79574d316 volume01]# ls
docker01.txt
进入 docker02 查看是否同步成功
[root@6a9129945bbe /]# docker attach docker02
[root@6a9129945bbe /]# cd volume01
[root@6a9129945bbe volume01]# ls
docker01.txt
--volume-from 相当于 继承
创建 docker03 (继承) 挂载于 docker02
[root@50cc8409521f /]# docker run -it --name docker03 --volumes-from docker02 oskari/centos:1.0 /bin/bash
[root@50cc8409521f /]# cd volume01
[root@50cc8409521f volume01]# ls
docker01.txt
[root@50cc8409521f volume01]# touch docker03.txt
分别进入 docker01 docker02 查看 volume01 目录下是否同步 docker03.txt 成功, 如果 docker03.txt 分别存在于 docker01 docker02 的 volume01 目录内, 说明容器间的数据共享成功
只要通过 --volume-from 命令挂载, 那么容器间就可以做到数据共享了, 同时共享数据的容器间, 如果容器被删除, 数据依然存在于运行中的容器中.依然可以访问. 可以理解为容器之间, 数据共享等同于 容器间的双向拷贝!
多个MySQL实现数据共享(思路,代码非验证)
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123123 --name mysql01 mysql:5.7
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123123 --name mysql02 --volume-from mysql01 mysql:5.7
结论:
容器之间配置信息的传递, 数据卷容器的生命周期一直持续到没有容器使用为止.
但是如果持久化到了本地, 这个时候, 本地的数据是不会删除的.
Dockerfile
Dockerfile介绍
Dockerfile 是用来构成Docker镜像文件的命令参数脚本
构建步骤:
- 编写一个Dockerfile文件
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像 (DockerHUB 阿里云镜像仓库)
Dockerfile构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 指令是从上到下顺序执行的
- "#" 表示注释
- 没一个指令都会创建提交一个新的镜像层,并提交.
Dockerfile是面向开发的. 我们以后要发布的项目, 做镜像, 就需要编写dockerfile文件.
Docker 镜像逐渐成为企业交付的标准, 必须掌握!
Dockerfile 文件的构建, 定义了一切的步骤以及源代码.
Docker images 通过 Dockerfile 构建生成的镜像, 最终发布和运行的产品.
Docker containers 容器就是镜像运行起来提供服务.
Dockerfile 指令
FROM # 基础镜像
MAINTAINER # 镜像作者 姓名+邮箱, 例如: Oskari < oskari@bengder.cc >
RUN # 镜像构建时需要运行的命令
ADD # 添加内容, 例如 tomcat 压缩包
WORKDIR # 镜像的工作目录
VOLUME # 挂载数据卷(目录)
EXPOSE # 指定暴露端口
CMD # 指定容器启动的时候要运行的命令, 只有最后一个会生效, 可以被替代
ENTRYPOINT # 指定容器启动的时候要运行的命令, 可以追加命令
ONBUILD # 当构建一个被继承 Dockerfile , 这个时候就会运行 ONBUILD 指令, 触发指令
COPY # 类似 ADD 命令, 将文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战测试①
Docker Hub 中大多数镜像都是 FROM scratch 开始的. 然后配置需要的软件和配置来进行构建.
- 编写 Dockerfile 文件
FROM centos
MAINTAINER Oskari<oskari@bengder.cc>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "IMAGE HAS BEEN BUILD SUCCESS!"
- 通过
Dockerfile文件构建镜像
COMMAND: docker build -f dockerfile文件路径 -t 镜像名:版本号
docker build -f mydockerfile-centos -t mycentos .
运行镜像创建容器
docker run -it mycentos:1.0 /bin/bash
[root@8e1170f6d9f9 local]# ls
bin etc games include lib lib64 libexec sbin share src
[root@8e1170f6d9f9 local]# pwd
/usr/local
[root@8e1170f6d9f9 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe12:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:12:00:03 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
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
inet6 ::1 prefixlen 128 scopeid 0x10<host>
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
[root@8e1170f6d9f9 local]# vim test.txt
[root@8e1170f6d9f9 local]#
可以看到基于centos我们设置了进入容器后的工作目录, 安装了ifconfig vim 工具.
我们可以列出本地镜像的变更历史 docker history
docker history mycentos:1.0 # 这里要使用 镜像名:版本号 或者 IMAGE ID
IMAGE CREATED CREATED BY SIZE COMMENT
cca92ffcc1b0 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/b... 0 B
3d83dcb4dbd9 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
5c0d7d6368f8 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
f7142fb9a548 9 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
cb37ff0fda19 9 minutes ago /bin/sh -c yum -y install net-tools 27.9 MB
d125a97e66e0 9 minutes ago /bin/sh -c yum -y install vim 65.5 MB
d4dbfdccb802 9 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0 B
96e44cb6ccfb 9 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0 B
d193dbeebed5 9 minutes ago /bin/sh -c #(nop) MAINTAINER Oskari<oskar... 0 B
300e315adb2f 8 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 8 months ago /bin/sh -c #(nop) LABEL org.label-schema.... 0 B
<missing> 8 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423... 209 MB
实现测试②
- 准备镜像文件
tomcat压缩包,JDK的压缩包
cd /home/build/tomcat # 路径自由,随意些, 做足下面软件以及文件的准备
apache-tomcat-9.0.52-fulldocs.tar.gz Dockerfile jdk-16.0.2_linux-aarch64_bin.tar.gz readme.txt
- 编写
Dockerfile( 官方建议使用 Dockerfile , 在使用build 命令时, 无需添加 -f 参数)
FROM centos
MAINTAINER Oskari<oskari@bengder.cc>
COPY readme.txt /usr/local/readme.txt
# 在找包的时候请注意要与系统内核相对应
ADD jdk-8u301-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.52.tar.gz /usr/local
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_301
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.52
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.52
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.52/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.52/logs/catalina.out
构建镜像
docker build -t tom .
启动镜像
# 挂载文件到宿主机并启动镜像
docker run -d -p 8090:8080 --name tomtest -v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.52/webapps/test -v /home/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.52/logs tom
查看挂载文件
访问容器
curl localhost:8090
可以看到正常返回的 html 代码. 亦可通过浏览器访问 IP:8090 查看容器状态是否正常运行
发布项目( 因为做了卷挂载, 所以在宿主机即可发布/编辑项目 )
/usr/build/tomcat/test/ 路径下创建 WEB-INF 文件夹, 创建配置文件 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLScheme-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
/usr/build/tomcat/test/ 路径下创建 index.jsp 文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
Hello World!<br/>
<%
out.println("你的 IP 地址 " + request.getRemoteAddr());
%>
</body>
</html>
访问 IP:8090/test/ , 会正常输出 Hello World! 等信息
发布自己的镜像
发布镜像到 Dockerhub
地址 https://hub.docker.com 注册账号
登陆账号
docker login -u YOUR_DOCKERHUB_ACCOUNT
Password: # 出现 Password 输入密码
Login Succeeded # 表示当前docker账户已登录
在服务器上进行镜像发布
docker push docker.io/zhangruoyucc/tom:1.0
Docker 网络
- lo 本机回环地址
- eth0 阿里云内网地址
- docker0 docker0地址
三个网络
Docker 是如何处理容器网络访问的?
首先,我们启动一个tomcat, 尝试宿主机是否能够 ping 通容器
原理
- 每启动一个docker容器, docker便会给容器分配一个IP, 宿主机只要安装了docker, 就会有一个网卡 docker0
桥接模式, 使用的技术是 veth-pair技术. - 容器网卡使用veth-pair技术, 生成承兑的虚拟设备接口. 一端连着协议, 一端彼此项链. 正因为有这个特性, veth-pair充当了一个桥梁
结论: 容器是共用的一个路由器, docker0
所有的容器不指定网络的情况下, 都是 docker0 路由的, docker会给我们的容器分配一个默认的可用IP
Docker 使用的是Linux 的桥接模式. 宿主机中, docker0 是Docker容器的网桥
Docker 中的所有网络接口都是虚拟的. 因为虚拟的转发效率高. 如果删除容器, 对应网桥也会取消设置.
--link 解决容器之间通信
如何解决容器间的网络连通问题?
可以看到通过 --link 命令我们创建了 tom2容器 到 tom1容器的数据通道, 但是tom1容器 无法ping通 tom2容器
查看Docker 网络配置信息
docker network --help
[root@Oskari~] # docker exec -it tom2 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3 tom1 7cb82177b466
172.18.0.4 4d702d6e5629
在使用 --link 配置了 tom1容器, 即把tom1容器的ip, 别名, 配置到了 /etc/hosts 文件内.
现在已经不建议使用 --link 进行容器间的通信了. 因为 docker0并不支持容器名连接访问
更多推荐



所有评论(0)