转自 狂神说
Docker安装
# 系统内核是3.10以上的
root@theSun:/# uname -r
4.4.0-185-generic
# 系统版本
root@theSun:/# cat /etc/os-release
文档:
https://docs.docker.com/engine/install/ubuntu/
阿里云镜像参考:
https://blog.csdn.net/xie1xiao1jun/article/details/79413436
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装 Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce
了解:
# 查看镜像
docker image
卸载:
1、卸载依赖
sudo apt-get purge docker-ce docker-ce-cli containerd.io
2、删除资源
sudo rm -rf /var/lib/docker
阿里云容器镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://9htdhp67.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker的常用命令
帮助命令
docker version
docker info
docker 命令 --help
帮助文档地址:https://docs.docker.com/reference/
镜像命令
docker images
-a, --all #列出所有镜像
-q, --quiet #只显示镜像id
docker search 搜索镜像
# 通过收藏来过滤
root@theSun:/var/lib/docker# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 9780 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3569 [OK]
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
root@theSun:/var/lib/docker# docker pull mysql
Using default tag: latest # 如果不写tag,默认就是latest
latest: Pulling from library/mysql
6ec8c9369e08: Pull complete # 分层下载,docker image的核心 联合文件系统
177e5de89054: Pull complete
ab6ccb86eb40: Pull complete
e1ee78841235: Pull complete
09cd86ccee56: Pull complete
78bea0594a44: Pull complete
caf5f529ae89: Pull complete
cf0fc09f046d: Pull complete
4ccd5b05a8f6: Pull complete
76d29d8de5d4: Pull complete
8077a91f5d16: Pull complete
922753e827ec: Pull complete
Digest: sha256:fb6a6a26111ba75f9e8487db639bc5721d4431beba4cd668a4e922b8f8b14acc #签名,防伪标志
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# 等价的
docker pull mysql
docker pull docker.io/library/mysql:latest
#指定版本下载
root@theSun:/var/lib/docker# docker pull mysql:5.7
5.7: Pulling from library/mysql
6ec8c9369e08: Already exists
177e5de89054: Already exists
ab6ccb86eb40: Already exists
e1ee78841235: Already exists
09cd86ccee56: Already exists
78bea0594a44: Already exists
caf5f529ae89: Already exists
4e54a8bcf566: Pull complete
50c21ba6527b: Pull complete
68e74bb27b39: Pull complete
5f13eadfe747: Pull complete
Digest: sha256:97869b42772dac5b767f4e4692434fbd5e6b86bcb8695d4feafb52b59fe9ae24
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
docker rmi -f 容器id #删除指定容器
docker rmi -f 容器id 容器id 容器id #删除多个容器
docker rmi -f $(docker images -aq) #删除全部容器
容器命令
说明:有了镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字 tomact01 tomcat02,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用)
-p 容器端口
容器端口
-p 随机指定端口
# 测试,启动并进入容器
root@theSun:/var/lib/docker# docker run -it centos /bin/bash
[root@c0cd544258f3 /]# ls # 查看容器内的centos,基础版本,很多命令都是不完善的
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
# 从容器中退回主机
[root@c0cd544258f3 /]# exit
exit
root@theSun:/var/lib/docker# ls
builder containers network plugins swarm trust
buildkit image overlay2 runtimes tmp volumes
列出所有的运行的容器
# docker ps 命令
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器+历史运行过的
-n=? # 显示最近创建的容器
-q # 只显示容器的编号
root@theSun:/var/lib/docker# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@theSun:/var/lib/docker# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c0cd544258f3 centos "/bin/bash" 4 minutes ago Exited (0) About a minute ago naughty_mcclintock
7dc103532dd1 hello-world "/hello" 25 hours ago Exited (0) 25 hours ago elegant_blackburn
退出容器
exit # 直接容器停止并退出
Ctrl+P+Q # 容器不停止退出
- 删除容器
docker rm 容器id # 删除指定的容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
启动和停止容器的操作
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id # 强制停止当前容器
常用其他命令
后台启动容器
# 命令 docker run -d 镜像名
docker run -d centos
# 问题docker ps,发现 centos 停止了
# 常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了。
查看日志
docker logs -f -t --tail [CONTAINER ID]
# 自己写一段shell脚本
docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1; done"
# 显示日志
-tf # 显示日志
--tail number # 要显示日志条数
docker logs -tf --tail 10 [CONTAINER ID]
查看容器中进程信息
docker top [容器id]
PID:当前进程id
PPID:父进程id
查看镜像的元数据
docker inspect [容器id]
进入当前正在运行的容器
# 通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id bashShell
# 测试
docker exect -it [容器id] /bin/bash
# 方法二
docker attach 容器id
# docker exec # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach # 进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
root@theSun:/home# docker attach 4ec656c03592
[root@4ec656c03592 /]# cd /home
[root@4ec656c03592 home]# ls
[root@4ec656c03592 home]# touch test.java
[root@4ec656c03592 home]# ls
test.java
[root@4ec656c03592 home]# exit
exit
root@theSun:/home# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ec656c03592 centos "/bin/bash" 2 minutes ago Exited (0) 6 seconds ago intelligent_goodall
c0cd544258f3 centos "/bin/bash" 12 hours ago Exited (0) 12 hours ago naughty_mcclintock
7dc103532dd1 hello-world "/hello" 37 hours ago Exited (0) 37 hours ago elegant_blackburn
# 拷贝
root@theSun:/home# docker cp 4ec656c03592:/home/test.java /home
root@theSun:/home# ls
test.java
# 拷贝是一个手动过程,未来可以使用 -v 卷的技术,可以实现自动同步
作业练习
Docker安装Nginx
# 1、搜索镜像 search 建议去dockerhub搜索
# 2、下载镜像 pull
# 3、运行测试
root@theSun:/home# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
root@theSun:/home# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 8679ced16d20 8 days ago 448MB
mysql latest e3fcc9e1cc04 8 days ago 544MB
nginx latest 8cf1bfb43ff5 9 days ago 132MB
centos latest 831691599b88 6 weeks ago 215MB
hello-world latest bf756fb1ae65 7 months ago 13.3kB
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
root@theSun:/home# docker run -d --name nginx01 -p 3389:80 nginx
4ece82f587c1aad352303f6e938a384dd5a130cab88965e3f08c475b291f7c14
root@theSun:/home# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ece82f587c1 nginx "/docker-entrypoint.…" 6 seconds ago Up 4 seconds 0.0.0.0:3389->80/tcp nginx01
root@theSun:/home# curl localhost:3389
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
...
# 进入容器
root@theSun:/home# docker exec -it nginx01 /bin/bash
root@4ece82f587c1:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@4ece82f587c1:/# cd /etc/nginx/
root@4ece82f587c1:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
root@4ece82f587c1:/etc/nginx#
思考:每次改动nginx配置文件,都需要进入容器内部?十分麻烦,如果可以在容器外部提供一个映射路径,达到在容器外部修改配置文件,容器内部就可以自动修改? -v 数据卷!
作业:docker装一个tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
#之前的启动都是后台,停止了容器之后,容器还可以查到 docker run -it --rm,一般用来测试,用完就删除【容器】
# 下载再启动
docker pull tomcat
# 启动运行
docker run -d -p 3389:8080 --name tomcat01 tomcat
# 测试访问没有问题
# 进入容器
root@theSun:/home# docker exec -it tomcat01 /bin/bash
# 发现问题:1、linux命令少了,2、没有webapps。阿里云镜像的原因。默认是最小的镜像,所有不必要的都剔除掉。保证最少可运行的环境。
思考:以后要部署项目,如果每次都要进入容器会很麻烦。要是可以在容器外部提供一个映射路径,webapps,在外部放置项目,自动同步到内部就好了!
作业:部署es + kibana
# es 暴露的端口很多
# es 十分消耗内存
# es 的数据一般需要放置到安全目录。挂载
# --net somenetwork ? 网络配置
# 启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.8.1
# 启动了 Linux就卡住了
#增加内存限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.8.1
# 查看 docker stats
思考:用kibana连接es,网络如何才能连接过去
可视化
- porttainer(先用这个)
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- 1
- Rancher(CI/CD 持续集成、部署再用)
什么是portainer: Docker 图形化界面管理工具,提供一个后台面板供操作。
平时不会用
Docker镜像讲解
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
如何得到镜像:
- 从远程仓库下载
- 朋友拷贝
- 自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
下载的时候看到的一层层就是这个。
UnionFS(联合文件系统)∶Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into asinglevirtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性∶一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot ilesystem)主要包含bootloader和kerne,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由botfs转交给内核,此时系统也会卸载bootfs。[个人理解:bootfs用于开机,rootfs用于命令。]
rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/de,/proc,/bin,/etc等标准目录和文件。roots就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
为什么虚拟机很大,Docker很小?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
虚拟机是分钟级别,容器是秒级!
分层原理
理解:
所有的Docker┌镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于UbuntuLinux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在Windows上仅支持windowsfiter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW【1】.
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就是我们通常说的容器层,容器之下的都叫镜像层。
如何提交一个自己的镜像
commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
实战测试
# 1、启动一个默认的tomcat
# 2、发现这个默认的tomcat没有webapps应用,镜像的原因,官方的默认镜像webapps下是没有文件的。
# 3、自己拷贝进去基本的文件
# 4、将操作过的容器通过commit提交为一个镜像,以后就用修改过的镜像即可。【类似于快照】
root@theSun:~# docker commit -a="thesun" -m="add webapps app" 09e54f1544b3 tomcat02:1.0
sha256:4f8525461d89ced0becbd7faa6cbc4d77534e2f502c346b5ddc07681dc3addcd
root@theSun:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 4f8525461d89 13 seconds ago 652MB
tomcat 9.0 9a9ad4f631f8 5 days ago 647MB
tomcat latest 9a9ad4f631f8 5 days ago 647MB
portainer/portainer latest 62771b0b9b09 11 days ago 79.1MB
mysql 5.7 8679ced16d20 11 days ago 448MB
mysql latest e3fcc9e1cc04 11 days ago 544MB
nginx latest 8cf1bfb43ff5 12 days ago 132MB
elasticsearch 7.8.1 a529963ec236 12 days ago 811MB
centos latest 831691599b88 6 weeks ago 215MB
hello-world latest bf756fb1ae65 7 months ago 13.3kB
容器数据卷
什么是容器数据卷
数据如果都在容器中,那么删除容器后,数据就会丢失。需求:数据可以持久化
即容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地!卷技术,目录的挂载,将容器内的目录,挂载到linux上。
总结:容器的持久化和同步操作,容器间也是可以数据共享的。
使用数据卷
方式一:直接使用命令来挂载 -v v:volume
docker run -it -v 主机目录:容器内目录
# 测试
root@theSun:/home# docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动后可以通过docker inspect 容器id
好处:以后修改只需要在本地修改即可,容器内会自动同步!
实战:安装MySQL
思考:MySQL的数据持久化问题!
# 获取镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载,安装启动mysql,需要配置密码
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -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=123456 --name mysql01 mysql:5.7
具名和匿名挂载
# 匿名挂载,在-v只写了容器内的路径,没有写容器外的路径。
-v 容器内路径
docker run -d -p --name nginx01 -v /etc/nginx nginx
# 查看多有的volume 情况
docker volume ls
# 具名挂载
# 通过
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx nginx
# 通过-v 卷名:容器内路径
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data
下
通过具名挂载可以方便地找到一个卷,大多数情况在使用具名挂载
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 具名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过-v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦设置了容器权限,容器对挂载出来的内容就有限定了
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
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的。
初识Dockerfile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本每个命令都是一层。
# 创建一个dockerfile文件,名字可以随机 建议 Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
# 这里每个命令就是镜像的一层
# 生成一个镜像,在创建镜像时就 挂载文件
# 此处相当于匿名挂载
docker build -f /home/docker-test-volume/dockerfile1 -t /thesun/centos:1.0 .
此种方式用的多,因为通常会构建自己的镜像,假设构建镜像时没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器
多个mysql同步数据!
docker run -d -p 3310:3306 -v /home/mysql/conf -v /home/mysql/data -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
结论:容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但一旦持久化到了本地,本地的数据是不会删除的!
DockerFile
DockerFIle介绍
dockerfile是用来构建docker镜像的文件!=命令参数脚本
构建步骤:
1、编写一个dockerfile文件
2、dockerbuild构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(DockerHub,阿里云镜像仓库!)
DockerFile构建过程
基础知识:
1、每个关键字(指令)都必须是大写字母
2、每个指令都会创建一个新的镜像层,并提交。
DockerFIle:构建文件,定义了一切的步骤,源代码
DockerImages:通过DOckerFIle构建生成的镜像,最终发布和运行的产品。
Docker容器:镜像运行起来提供服务。
DockerFile的指令
FROM #基础镜像,一些从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建的时候需要运行的命令
ADD #步骤:tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录
EXPOSE #暴露端口配置
CMD #指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承的DockerFile就会运行ONBUILD指令。触发指令
COPY #类似ADD,将文件拷贝到镜像中
ENV #构建的时候设置环境变量
实战测试
# 1 编写DockerFIle文件
FROM centos
MAINTAINER thesun<1498347810@qq.com>
#相当于定义一个变量
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 添加vim 和 net-tools功能
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end-----"
#启动后进入哪个命令行
CMD /bin/bash
# 2 通过文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] .
root@theSun:/home/dockerfile# docker build -f mydockerfile-centos -t mycentos:0.1 .
# 通过history可以列出本地进行的变更历史
docker history 镜像id
CMD 和 ENTRYPOINT区别
CMD #指定这个容器启动时要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动时候要运行的命令,可以追加命令
测试cmd
vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 构建镜像
root@theSun:/home/dockerfile# docker build -f dockerfile-cmd-test -t cmdtest .
# run运行,发现ls -a生效
root@theSun:/home/dockerfile# docker run 74e69730ee78
# 想追加一个命令 -l即 ls -al
root@theSun:/home/dockerfile# docker run 74e69730ee78 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
# -l 替换了CMD ["ls","-a"]命令,-l不是命令所以报错!
测试 ENTRYPOINT
vim dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls","-a"]
# 追加的命令,是直接拼接在ENTRYPOINT命令的后面!
# ls -al
docker run [容器id] -l 不会报错
实战:Tomcat镜像
1、准备镜像文件 tomcat压缩包,jdk压缩包。
2、编写dockerfile文件
FROM centos
MAINTAINER thesun<123@qq.com>
COPY readme.txt /usr/local/readme.txt
# ADD命令会自动解压
ADD jdk-8u261-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.37.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_261
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.37
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.37
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.37/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.37/bin/logs/catalina.o
ut
3、构建镜像
# 将文件命名为Dockerfile,就不用加-f。会自动在当前目录下查找
root@theSun:/home/build# docker build -t diytomcat .
- 1
- 2
4、启动镜像
docker run -d -p 9090:8080 --name thesuntomcat -v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.37/webapps/test -v /home/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.37/logs diytomcat
5、访问测试
6、发布项目(由于做了卷挂载,直接在本地编写项目就可以发布了!)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-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>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, theSun!!</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("----my test web logs----")
%>
</body>
</html>
发现:项目部署成功!
以后开发的步骤:需要掌握DOckerfile的编写!以后一切都是使用docker镜像来发布运行!
发布自己的镜像
DockerHub
# 登录
docker login -u [username]
# 提交镜像
docker push diytomcat
# 增加一个tag
#自己发布的镜像尽量带上版本号
docker tag [镜像Id] thesun/tomcat:1.0
阿里云镜像服务上
1、登录阿里云
2、找到容器镜像服务
3、创建命名空间
4、创建容器镜像
参考官方文档
Docker网络
理解Docker0
# 问题,docker是如何处理容器网络访问的?
docker run -d -P --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr ,发现容器启动的时候会得到一个eth0@if121 ip地址,docker分配的!
root@theSun:/# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
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
120: eth0@if121: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 宿主机可以通过此ip地址ping通该容器。
原理
1、每启动一个docker容器,docker就会给docker容器分配一个Ip,只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术是evth-pair
# 发现容器的网卡,都是一对一对的
# evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连。正因为有这个特性,evth-pair可以充当一个桥梁,用于连接各种虚拟网络设备。
# OpenStack,DOcker容器之间的连接,ovs的连接,都是使用evth-pair技术
结论:tomcat01和tomcat02是共用一个路由器,docker0.
所有的容器不指定网络的情况下,都是docker0路由的,docker会给容器分配一个默认的可用IP
Docker中的所有网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件)
–link
思考一个场景:编写了一个微服务,database url=ip: , 项目不重启,数据库ip换掉了,希望可以用名字来访问容器。
docker run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 ping tomcat02
–link 就是在hosts配置中增加了一个映射
已不建议使用
自定义网络
查看所有的docker网络
docker network ls
网络模式
bridge:桥接 docker默认,自己创建也使用bridge模式
none:不配置网络
host:和宿主机共享网络
container:容器网络连通(用得少,局限大)
# 直接启动的命令 默认带--net bridge,就是docker0
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点:默认,域名不能访问, --Link可以打通连接,但不建议使用
# 可以自定义一个网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker network inspect mynet # 查看网络具体详情
# 使用自己定义的网络创建容器
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
# 现在不使用--link ,就可以通过容器名相互ping通
docker exec -it tomcat-net-01 ping tomcat-net-02
# 自定义的网络可以自动维护对应的关系,推荐平时这样使用网络。
# 好处:使用redis集群搭建一个网络,mysql再搭建一个,不同的集群使用不同的网络,保证集群是安全和健康的。
网络连通
不同网段下的容器互相连通。(docker0网段下的tomcat连通mynet网络)
docker network connect mynet tomcat01
# 连通之后就是将tomcat01放到了mynet网络下。
# 一个容器两个ip地址!类似于公网ip,私网ip
结论:如果要跨网络操作别人,就需要使用docker network connect连通!
实战:部署Redis集群
# 通过脚本创建六个redis配置
for port in $(seq 1 6);
do
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
docker run -p 637${port}:6379 -p 1637${port]:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 创建集群
redis-c1-cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
SpringBoot微服务打包Docker镜像
预告:如果有很多镜像,如何维护?
企业实战
Docker Compose
简介
原先dockerfile build run,需要手动操作,单个容器
Docker Compose 可以高效管理容器,定义运行多个容器。
作用:批量容器编排
Compose是Docker官方的开源项目。需要安装!
web服务,redis,mysql,nginx……多个容器,通过compose可以快速启动。
Compose重要概念:
- 服务services,容器应用。(web,redis,mysql…)
- 项目project。一组关联的容器。 博客,web,mysql wp
安装Compose
1、下载
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 备用地址,比较快
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-'uname -s'-'uname-m' > /usr/local/bin/docker-compose
- 1
- 2
- 3
- 4
2、授权
chmod +x /usr/local/bin/docker-compose
- 1
getting start体验
官方地址:https://docs.docker.com/compose/gettingstarted/
python应用,计数器,redis
1、应用 app.py
2、Dockerfile 应用打包为镜像
3、Docker-compose yml 文件(定义整个服务需要的环境:web, redis)
4、启动compose项目(docker-compose up)
默认的服务名 文件名_服务名_num
多个服务器 集群 A B _num副本数量
服务redis服务 =》4个副本
集群状态,服务都不可能只有一个运行实例。弹性
网络规则:
项目中的内容都在同个网络下。可通过名称访问(需要在同一网络下),保证了高可用
停止:docker-compose down ctrl+c
以前都是单个docker run启动容器,docker-compose通过yml配置文件,可以通过compose一键启动所有服务、停止
yaml规则
Docker Swarm
集群的方式部署
CI/CD Jenkins流水线