Docker
查看服务器环境 uname -r
查看系统配置 cat /etc/os-release
安装,根据安装文档安装。
- curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
- 卸载旧版::sudoyum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
- 设置仓库 sudoyum install -y yum-utils \device-mapper-persistent-data \lvm2
- 配置阿里源
- sudo yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装 Docker Engine-Community
$ sudo yum install docker-ce docker-ce-cli containerd.io
- 也可以安装指定版本
yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
$ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
- 启动 $ sudo systemctl start docker
- 测试 $ sudo docker run hello-world
安装完成
卸载:
- 删除安装包:
yum remove docker-ce
- 删除镜像、容器、配置文件等内容:
rm -rf /var/lib/docker
阿里云镜像加速
配置使用:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://c02bj2qd.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
分析docker是如何实现hello world
docker是怎么工作的?
Docker是一个client-server 结构的系统,Docker的守护进程运行在主机上,通过socet从客户端访问
DockerServer接收到一个Docker——client的指令,就会执行这个命令。
docker为什么比vm快?
- docker比VM有着更少的抽象层
总结:新建一个容器的时候,docker不需要像VM一样重新加载一个操作系统内核,避免引导。虚拟机是加载guestOS,分钟级别。而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级。
Docker常用命令:
帮助命令:
docker version #显示docker版本信息
docker info #显示docker系统信息
docker --help #帮助命令
其他查看帮助文档地址即可
镜像命令
docker images 查看所有本地主机上面的镜像
[root@zz ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 8 months ago 13.3kB
REPOSITORY 镜像仓库资源
TAG 镜像标签
IMAGE ID 镜像id
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
[root@zz ~]# docker images --help
Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
-a, --all Show all images (default hides intermediate images)
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
-q, --quiet Only show image IDs
# -a列出所有镜像
# -q, --quiet 只显示镜像的id
docker search 搜索镜像
[root@zz ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12618 [OK]
mariadb MariaDB Server is a high performing open sou… 4847
#可选项
通过收藏来过滤
-- filter=stars=3000 搜索出的镜像就是STARS大于3000的
[root@ZZ ~]# docker search MYSQL --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12618 [OK]
mariadb MariaDB Server is a high performing open sou… 4847 [OK]
docker pull
[root@zzz /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
删除镜像
docker rmi -f 容器id #删除指定容器
docker rmi -f 容器id 容器id 容器id #删除多个容器
docker rmi -f $(docker images -aq) #删除全部容器
容器命令
说明:有了镜像才可以创建容器,下载一个centOS镜像。
docker pull centos
新建容器并启动:
docker run [可选参数] image
--name= 'name' 容器名字
-d 后台运行方式
-it 使用交互方式运行,进入容器查看内容
-p 容器端口
[root@iZ0jl2xqw866y70pqflxpdZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 c20987f18b13 5 months ago 448MB
hello-world latest feb5d9fea6a5 8 months ago 13.3kB
centos latest 5d0da3dc9764 8 months ago 231MB
[root@iZ0jl2xqw866y70pqflxpdZ ~]# docker run -it centos /bin/bash
[root@7f322afd4780 /]#
[root@7f322afd4780 /]# ls #查看容器内的centOS
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
退出 exit
退出不停止 Ctrl p q 容器退出不停止
删除容器
docker ps -a #查看容器
docker rm 容器id #删除指定容器
docker rm -f $(docker ps -aq) 删除所有容器
docker start 容器id #容器id
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
后台启动容器
docker run -d 镜像名
查看日志
docker logs -f -t --tail 镜像名
查看容器中的进程信息
docker top
查看镜像元数据
docker inspect
进入当前正在运行的容器
docker exec -it 容器id bashShell
docker attach -it 容器id /bin/bash
从容器内拷贝文件到主机上
docker cp 容器id :容器内路径 目的主机路径
Docker 安装Nginx
- 搜索镜像 docker search nginx
- 下载镜像 docker pull nginx
- 启动指定对外暴露端口 docker run -d --name nginx01 -p 80:80 nginx (-d:后台运行;-name:给容器取别名;-p:外部服务器端口:容器内部端口)
[root@iZ0jl2xqw866y70pqflxpdZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f1f245e7159 nginx "/docker-entrypoint.…" 19 seconds ago Up 19 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx01
a8db001282dd centos "/bin/bash" 18 hours ago Up 18 hours goofy_mccarthy
[root@iZ0jl2xqw866y70pqflxpdZ ~]# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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>
进入容器: docker exec -it nginx01 /bin/bash
root@7f1f245e7159:/# whereis nginxnginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginxroot@7f1f245e7159:/# cd /etc/nginxroot@7f1f245e7159:/etc/nginx# lsconf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_paramsroot@7f1f245e7159:/etc/nginx#
Docker安装Tomcat
- 官方使用
- docker run -it --rm tomcat:9.0 (作为测试使用,用完即删除)
- 下载再启动
docker pull tomcat:9.0
docker run -d -p 80:8080 --name tomcat01 tomcat - 进入容器
docker exec -it tomcat01 /bin/bash - 问题点:
- Linux命令少了
- 没有webapps,可从外部copy
root@31d944877c19:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@31d944877c19:/usr/local/tomcat# cd webapps
root@31d944877c19:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@31d944877c19:/usr/local/tomcat/webapps# exit
exit
[root@iZ0jl2xqw866y70pqflxpdZ ~]# curl localhost:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/10.0.14</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">
<div id="navigation" class="curved container">
<span id="nav-home"><a href="https://tomcat.apache.org/">Home</a></span>
<span id="nav-hosts"><a href="/docs/">Documentation</a></span>
<span id="nav-config"><a href="/docs/config/">Configuration</a></span>
<span id="nav-examples"><a href="/examples/">Examples</a></span>
<span id="nav-wiki"><a href="https://wiki.apache.org/tomcat/FrontPage">Wiki</a></span>
<span id="nav-lists"><a href="https://tomcat.apache.org/lists.html">Mailing Lists</a></span>
<span id="nav-help"><a href="https://tomcat.apache.org/findhelp.html">Find Help</a></span>
<br class="separator" />
</div>
<div id="asf-box">
<h1>Apache Tomcat/10.0.14</h1>
</div>
<div id="upper" class="curved container">
<div id="congrats" class="curved container">
<h2>If you're seeing this, you've successfully installed Tomcat. Congratulations!</h2>
</div>
<div id="notice">
<img id="tomcat-logo" src="tomcat.svg" alt="[tomcat logo]" />
<div id="tasks">
<h3>Recommended Reading:</h3>
<h4><a href="/docs/security-howto.html">Security Considerations How-To</a></h4>
<h4><a href="/docs/manager-howto.html">Manager Application How-To</a></h4>
<h4><a href="/docs/cluster-howto.html">Clustering/Session Replication How-To</a></h4>
</div>
</div>
<div id="actions">
<div class="button">
<a class="container shadow" href="/manager/status"><span>Server Status</span></a>
</div>
<div class="button">
<a class="container shadow" href="/manager/html"><span>Manager App</span></a>
</div>
<div class="button">
<a class="container shadow" href="/host-manager/html"><span>Host Manager</span></a>
</div>
</div>
<br class="separator" />
</div>
<div id="middle" class="curved container">
<h3>Developer Quick Start</h3>
<div class="col25">
<div class="container">
<p><a href="/docs/setup.html">Tomcat Setup</a></p>
<p><a href="/docs/appdev/">First Web Application</a></p>
</div>
</div>
<div class="col25">
<div class="container">
<p><a href="/docs/realm-howto.html">Realms & AAA</a></p>
<p><a href="/docs/jndi-datasource-examples-howto.html">JDBC DataSources</a></p>
</div>
</div>
<div class="col25">
<div class="container">
<p><a href="/examples/">Examples</a></p>
</div>
</div>
<div class="col25">
<div class="container">
<p><a href="https://wiki.apache.org/tomcat/Specifications">Servlet Specifications</a></p>
<p><a href="https://wiki.apache.org/tomcat/TomcatVersions">Tomcat Versions</a></p>
</div>
</div>
<br class="separator" />
</div>
<div id="lower">
<div id="low-manage" class="">
<div class="curved container">
<h3>Managing Tomcat</h3>
<p>For security, access to the <a href="/manager/html">manager webapp</a> is restricted.
Users are defined in:</p>
<pre>$CATALINA_HOME/conf/tomcat-users.xml</pre>
<p>In Tomcat 10.0 access to the manager application is split between
different users. <a href="/docs/manager-howto.html">Read more...</a></p>
<br />
<h4><a href="/docs/RELEASE-NOTES.txt">Release Notes</a></h4>
<h4><a href="/docs/changelog.html">Changelog</a></h4>
<h4><a href="https://tomcat.apache.org/migration.html">Migration Guide</a></h4>
<h4><a href="https://tomcat.apache.org/security.html">Security Notices</a></h4>
</div>
</div>
<div id="low-docs" class="">
<div class="curved container">
<h3>Documentation</h3>
<h4><a href="/docs/">Tomcat 10.0 Documentation</a></h4>
<h4><a href="/docs/config/">Tomcat 10.0 Configuration</a></h4>
<h4><a href="https://wiki.apache.org/tomcat/FrontPage">Tomcat Wiki</a></h4>
<p>Find additional important configuration information in:</p>
<pre>$CATALINA_HOME/RUNNING.txt</pre>
<p>Developers may be interested in:</p>
<ul>
<li><a href="https://tomcat.apache.org/bugreport.html">Tomcat 10.0 Bug Database</a></li>
<li><a href="/docs/api/index.html">Tomcat 10.0 JavaDocs</a></li>
<li><a href="https://github.com/apache/tomcat/tree/10.0.x">Tomcat 10.0 Git Repository at GitHub</a></li>
</ul>
</div>
</div>
<div id="low-help" class="">
<div class="curved container">
<h3>Getting Help</h3>
<h4><a href="https://tomcat.apache.org/faq/">FAQ</a> and <a href="https://tomcat.apache.org/lists.html">Mailing Lists</a></h4>
<p>The following mailing lists are available:</p>
<ul>
<li id="list-announce"><strong><a href="https://tomcat.apache.org/lists.html#tomcat-announce">tomcat-announce</a><br />
Important announcements, releases, security vulnerability notifications. (Low volume).</strong>
</li>
<li><a href="https://tomcat.apache.org/lists.html#tomcat-users">tomcat-users</a><br />
User support and discussion
</li>
<li><a href="https://tomcat.apache.org/lists.html#taglibs-user">taglibs-user</a><br />
User support and discussion for <a href="https://tomcat.apache.org/taglibs/">Apache Taglibs</a>
</li>
<li><a href="https://tomcat.apache.org/lists.html#tomcat-dev">tomcat-dev</a><br />
Development mailing list, including commit messages
</li>
</ul>
</div>
</div>
<br class="separator" />
</div>
<div id="footer" class="curved container">
<div class="col20">
<div class="container">
<h4>Other Downloads</h4>
<ul>
<li><a href="https://tomcat.apache.org/download-connectors.cgi">Tomcat Connectors</a></li>
<li><a href="https://tomcat.apache.org/download-native.cgi">Tomcat Native</a></li>
<li><a href="https://tomcat.apache.org/taglibs/">Taglibs</a></li>
<li><a href="/docs/deployer-howto.html">Deployer</a></li>
</ul>
</div>
</div>
<div class="col20">
<div class="container">
<h4>Other Documentation</h4>
<ul>
<li><a href="https://tomcat.apache.org/connectors-doc/">Tomcat Connectors</a></li>
<li><a href="https://tomcat.apache.org/connectors-doc/">mod_jk Documentation</a></li>
<li><a href="https://tomcat.apache.org/native-doc/">Tomcat Native</a></li>
<li><a href="/docs/deployer-howto.html">Deployer</a></li>
</ul>
</div>
</div>
<div class="col20">
<div class="container">
<h4>Get Involved</h4>
<ul>
<li><a href="https://tomcat.apache.org/getinvolved.html">Overview</a></li>
<li><a href="https://tomcat.apache.org/source.html">Source Repositories</a></li>
<li><a href="https://tomcat.apache.org/lists.html">Mailing Lists</a></li>
<li><a href="https://wiki.apache.org/tomcat/FrontPage">Wiki</a></li>
</ul>
</div>
</div>
<div class="col20">
<div class="container">
<h4>Miscellaneous</h4>
<ul>
<li><a href="https://tomcat.apache.org/contact.html">Contact</a></li>
<li><a href="https://tomcat.apache.org/legal.html">Legal</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
</ul>
</div>
</div>
<div class="col20">
<div class="container">
<h4>Apache Software Foundation</h4>
<ul>
<li><a href="https://tomcat.apache.org/whoweare.html">Who We Are</a></li>
<li><a href="https://tomcat.apache.org/heritage.html">Heritage</a></li>
<li><a href="https://www.apache.org">Apache Home</a></li>
<li><a href="https://tomcat.apache.org/resources.html">Resources</a></li>
</ul>
</div>
</div>
<br class="separator" />
</div>
<p class="copyright">Copyright ©1999-2022 Apache Software Foundation. All Rights Reserved</p>
</div>
</body>
</html>
Docker部署ES+kibana
- ES暴露的端口很多。
- ES占用内存较大。
- ES的数据一般都需要放置到安全目录下。
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:8.2.0
docker stats 查看CPU的状态
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d --name elasticsearch01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx512m" elasticsearch:7.6.2
3b8cd4991814896c523ee67b84ce198e32bd82b1a62d512b198138a58ca946f1
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b8cd4991814 elasticsearch:7.6.2 "/usr/local/bin/dock…" 10 seconds ago Up 6 seconds 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch01
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker stats
如何使用kibanan连接ES
可视化
- portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7789d4505a00 portainer/portainer "/portainer" 6 seconds ago Up 5 seconds 0.0.0.0:8088->9000/tcp quirky_sinoussi
Docker镜像
原理
UnionFS 联合文件系统
bootfs:boot file system
rootfs:root file system
Docker镜像都是只读的,当容器启动时,一个新的可写层被加到镜像的顶部,这一层就是我们通常说的容器层,容器层之下的都叫镜像层
commit提交镜像
docker commit # 提交容器成为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:
[Tag]
docker images
docker run -it -p 8080:8080 tomcat
将webapps.dist里面所有的文件拷贝到webapps里面,其中-r必须有,表示目录递归拷贝
docker commit -a="zhangtao" -m="add webapps app" 当前容器的id tomcat02:1.0
接下来三个部分是docker的精髓
容器数据卷
什么是容器卷
docker是要将应用和环境打包成一个镜像
这样,数据就不应该在容器中,否则容器删除,数据就会丢失,这就是删库跑路
故容器之间要有一个数据共享技术
在Docker容器中产生的数据,同步到本地,这就是卷技术
本质上是一个目录挂载,将容器内的目录挂载到虚拟机上
使用数据卷
docker run -it -v 主机目录:容器内目录 镜像名/id /bin/bash
eg:docker run -it -v /home/test:/home centos /bin/bash
#启动起来之后可以通过 docker inspect 容器id 查看具体挂载情况
指定路径挂载;将容器内指定目录挂载到本地指定目录。
测试文件同步
再次验证,停掉容器后,在宿主机上修改文件,然后启动容器,查看容器内文件是否同步。
优点:以后修改内容只需要在本地修改即可,容器内会自动同步。
安装MySQL
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
-d:后台运行
-p:端口映射
-v:卷挂载
-e:环境配置
--name:容器名字
#启动成功后可通过本地Navicat连接
本地创建数据库,查看映射路径是否存在相应的数据。
总结:即使删除容器也不会删除数据,因为数据已经挂载到了本地。这便是容器中的数据持久化工程。
具名和匿名挂载
#匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /ect/nginx nginx
[root@iZ0jl2xqw866y70pqflxpdZ /]# docker run -d -P --name nginx01 -v /ect/nginx nginx
fae913a2b70a4a923dd1342913e59547827b643048eb33d13c00752f184732de
#查看所有 volume 的挂载情况
[root@iZ0jl2xqw866y70pqflxpdZ /]# docker volume ls
DRIVER VOLUME NAME
local 2f967a395859439cd5294d57f0ddc251f77440f44cf46891a81f34bd0f169ec3
local 7a9f9e7e09554cd097f03a33cd8332e38f6105849520dd00d232608047ac1317
local 76faef5c19074d68c05b2470c6035ee3b17e6c800ba8a44614a3273699e26864
local a053fd8a1b6940958eea85752d273625e90aea03ad899f3111f5912102dc0dc6
具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@iZ0jl2xqw866y70pqflxpdZ home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
4a56bfefd701d245b48661294c3b3b2e91f5e3d50642a124f3869f025e9345b5
[root@iZ0jl2xqw866y70pqflxpdZ home]# docker volume ls
DRIVER VOLUME NAME
local 2f967a395859439cd5294d57f0ddc251f77440f44cf46891a81f34bd0f169ec3
local juming-nginx
#通过 -v 卷名:容器内路径
#查看一下这个卷
docker volume inspect juming-nginx
所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #匿名挂载
-v /宿主机路径::容器内路径 #指定路径挂载
拓展:
#通过 -v 容器内路径,:ro rw 改变读写权限
ro read only 只读
rw read write 可读可写
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 只能通过宿主机来改变,容器内部无法对其进行操作
DockerFile
用来构建docker镜像的构建文件! 命令脚本
文件内容 ,指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end------"
CMD /bin/bash
[root@iZ0jl2xqw866y70pqflxpdZ docker-test-volume]# docker build -f /home/docker -test-volume/dockefile1 -t zhang/cenos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 528cd41ef8fe
Removing intermediate container 528cd41ef8fe
---> d1fd74ab0144
Step 3/4 : CMD echo "-----end------"
---> Running in 8df59f0ea5e9
Removing intermediate container 8df59f0ea5e9
---> 67d5334069e8
Step 4/4 : CMD /bin/bash
---> Running in 33f2538f4f1a
Removing intermediate container 33f2538f4f1a
---> 0f6925ae4108
Successfully built 0f6925ae4108
Successfully tagged zhang/cenos:1.0
[root@iZ0jl2xqw866y70pqflxpdZ docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zhang/cenos 1.0 0f6925ae4108 18 seconds ago 231MB
docker run -it 0f6925ae4108 bash
这个卷和外部一定有一个同步的目录
数据卷容器
多个mysql同步数据
结论:容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦持久化到了本地,这个时候本地的数据是不会删除的
方式二
DockerFile
dockerfile是用来构建docker镜像的文件,命令参数脚本。
构建步骤:
- 编写dockerfile文件
- docker build 构建成为镜像
- docker run 运行镜像
- docker push 发布镜像(dockerHub ,阿里云镜像仓库)
DockerFile 构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下依次执行
- 表示注释 #
- 每个指令都会创建一个新的镜像层,并提交!
dockerfile 是面向开发的,后期发布项目,做镜像,就需要填写dockerfile文件。
步骤:开发,部署,上线运维
DockerFile:构建文件,定义了一切步骤,源代码
DockerImage:通过dockerFile构建生成镜像,最终发布和运行。
Docker容器:容器就是镜像运行起来提供服务器
DockerFile的指令
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像谁写的 姓名+邮箱
RUN #镜像构建时候需要运行的命令
ADD #步骤,Tomcat镜像,添加内容
WORKDIR #镜像的工作目录
VOLUME #挂载目录
EXPOST #暴露端口配置
CMD #指定这个容器启动时候运行的命令,只有最后一个会生效,可被替代.
ENTRYPOINT #指定这个容器启动时候运行的命令,可以追加命令
ONBUILD #当构建一个被继承的dockerfile这个时候就会运行ONBUILD的指令,触发指令
COPY #类似ADD,将文件拷贝到镜像中
ENV #构建的时候设置环境变量
实战测试
创建自己的centos
1、编写docker文件
FROM centos
MAINTAINER zhangtao<valiant_tao@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN -y install vim
RUN -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "=====end======"
CMD /bin/bash
2、通过文件构建镜像
[root@iZ0jl2xqw866y70pqflxpdZ dockerfile]# docker build -f mydockerfile -t mycentos:0.1 .
Sending build context to Docker daemon 2.048kB
Step 1/10 : FROM centos
---> 5d0da3dc9764
Step 2/10 : MAINTAINER zhangtao<valiant_tao@163.com>
---> Running in 380047d878f4
Removing intermediate container 380047d878f4
---> f6c1cd9466f7
Step 3/10 : ENV MYPATH /usr/local
---> Running in 64684f9d48d4
Removing intermediate container 64684f9d48d4
---> a2e08c66cc9a
Step 4/10 : WORKDIR $MYPATH
---> Running in afd0ddaec852
Removing intermediate container afd0ddaec852
---> bac51352c813
Step 5/10 : RUN -y install vim
---> Running in fc118b0d04a8
/bin/sh: -y: invalid option
Usage: /bin/sh [GNU long option] [option] ...
/bin/sh [GNU long option] [option] script-file ...
GNU long options:
--debug
--debugger
--dump-po-strings
--dump-strings
--help
--init-file
--login
--noediting
--noprofile
--norc
--posix
--rcfile
--rpm-requires
--restricted
--verbose
--version
Shell options:
-ilrsD or -c command or -O shopt_option (invocation only)
-abefhkmnptuvxBCHP or -o option
The command '/bin/sh -c -y install vim' returned a non-zero code: 2
查看镜像变更历史:docker history 镜像id
CMD 和 ENTRYPOINT区别
CMD #指定容器启动时执行,只有最后一次会生效,可被提地啊
ENTRYPOINT #指定这个容器启动的时执行,可被追加
实战:Tomcat镜像
- 准备镜像文件 Tomcat压缩包,JDK压缩包
- 编写dockerfile文件
发布镜像
DockerHub
[root@iZ0jl2xqw866y70pqflxpdZ dockerfile]# docker login -u valiantao
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
阿里云镜像服务
- 登录阿里云
- 容器镜像服务
- 创建命名空间
- 创建容器镜像
Docker网络
Docker网络ip
查看本地网络信息 ip addr
可见有三个网卡信息,lo:本地 ;ens:虚拟机或阿里云服务器地址;docker0:docker网络地址。
查看docker容器启动时的内部网络;分别启动两个容器;
[root@node1 ~]# docker exec -it tomcat01 ip addr
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
6: eth0@if7: <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
[root@node1 ~]#
[root@node1 ~]# docker exec -it tomcat02 ip addr
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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@node1 ~]#
容器与容器之间,容器与docker0之间是可以连接的;
[root@node1 ~]# docker exec -it tomcat01 ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.845 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.130 ms
64 bytes from 172.17.0.1: icmp_seq=4 ttl=64 time=0.134 ms
64 bytes from 172.17.0.1: icmp_seq=5 ttl=64 time=0.119 ms
64 bytes from 172.17.0.1: icmp_seq=6 ttl=64 time=0.082 ms
docker每启动一个容器,就会分配一个ip,只要安装了docker,就会有一个网卡docker0,桥接模式,使用的时veth-pair技术。
启动容器后再次测试ip addr;
可以看到容器内ip与本机ip成对出现,这就是veth-pair技术。
docker0相当于一个路由器,各个容器都与docker0相连,容器之间的通信通过路由器来转发。
Docker中的所有网络接口都是虚拟的,相当于内网传递;
只要删除容器,对应网络就会删除。
--link
需求,每次重启容器或Linux,ip就会变化,固定的ip互联网络就会失效,如何使用服务名来连接,而不考虑ip?
测试使用容器名来ping
[root@node1 ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
[root@node1 ~]#
容器之间无法通过容器名来连接;
如何解决?
[root@node1 ~]# docker run -d -P --name tomcat02 --link tomcat01 tomcat
81d38e78eea0756c654af6b51ac626ad7c086a7fe56589303ddb108fd0091f8d
[root@node1 ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.120 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.184 ms
^C
--- tomcat01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.120/0.152/0.184/0.032 ms
# 但是反向却无法链接通!!!
tomcat02能够通过容器名链接tomcat01,原理是--link 是通过tomcat02在自己容器hosts文件中配置了tomcat01 ip信息!
[root@node1 ~]# docker exec -it tomcat02 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.17.0.2 tomcat01 e0559dd36be0
172.17.0.3 81d38e78eea0
本质就是修改host映射,--link已经摒弃;建议实现使用自定义网络实现!
自定义网络
查看本地docker网络信息
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8d5e54eaae69 bridge bridge local
3452d41b8d68 host host local
c98ef8bfc64b none null local
- bridge : 桥接(默认,自己创建也使用bridge)
- host : 和宿主即共享
- none : 不配置网络
# 在我们启动容器的时候默认会有一个网络设置
docker run -d -P --net bridge --name tomcat01 tomcat
# 所以我们可以指定自定义的网络
# 通过docker network --help
[root@node1 ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
创建自定义的网络
docker create
[root@node1 ~]# docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
30d7111860cf9c3aa2739ff90a75e309980f0e59b71447318982bbeef0d37442
-d --driver 网络模式
--subnet 子网
--gateway 网关
---------------------------------------------
# 命令参数详解
[root@node1 ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
查看我们创建的网络
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
8d5e54eaae69 bridge bridge local
3452d41b8d68 host host local
30d7111860cf mynet bridge local
c98ef8bfc64b none null local
[root@node1 ~]#
可以实现不同集群使用不同的网络,保证集群网络的安全和健康;
如Redis集群在192.160.0.0/16网段下,mysql集群在192.161.0.0/16网段下。
网络连通
场景:
解决: 使用docker network connect
实现。
测试连通:
[root@node1 ~]# docker network connect mynet tomcat01
# 查看mynet网络信息
[root@node1 ~]# docker network inspect 30d7111860cf
可以看到mynet将tomcat01容器添加到自己网络中;
这就是一个容器两个ip;
查看tomcat01容器网络信息
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e653420cdecd tomcat "catalina.sh run" 3 minutes ago Up 3 minutes 0.0.0.0:49159->8080/tcp tomcat01
0ebe12ac83db tomcat "catalina.sh run" 6 minutes ago Up 6 minutes 0.0.0.0:49158->8080/tcp tomcat02-net
33d8bc6a2bea tomcat "catalina.sh run" 6 minutes ago Up 6 minutes 0.0.0.0:49157->8080/tcp tomcat01-net
[root@node1 ~]# docker inspect e653420cdecd
原本属于docker0网段的容器,添加了mynet网络;
测试连通:
[root@node1 ~]# docker exec -it tomcat01 ping tomcat01-net
PING tomcat01-net (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01-net.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.121 ms
64 bytes from tomcat01-net.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.064 ms
^C
--- tomcat01-net ping statistics ---
## bingo!!
Redis集群部署
shell脚本
# 创建redis网卡
docker network create redis --subnet 192.168.0.0/16
# 通过脚本创建六个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
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.169.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 192.169.0.1${port} redis:5.0.9-alpine3.11 /etc/redis/redis.conf; \
#创建redis集群
redis0-cli --cluster create 172.169.0.11:6379 172.169.0.12:6379 172.169.0.13:6379 172.169.0.14:6379 172.169.0.15:6379 172.169.0.16:6379 --cluster-replicas
Docker Compose
Docker Compose用来管理容器,定义运行多个容器。
官方介绍
Compose is a tool for defining and running multi-container Docker applications.With Compose, you use a YAML file to configure your application’s services.Then, with a single command, you create and start all the servicesfrom your configuration. To learn more about all the features of Compose,see the list of features.
Compose works in all environments: production, staging, development, testing, aswell as CI workflows. You can learn more about each case in Common UseCases.
三步骤:
Using Compose is basically a three-step process:
- Define your app’s environment with a
Dockerfile
so it can be reproducedanywhere. - Define the services that make up your app in
docker-compose.yml
so they can be run together in an isolated environment. - Run
docker compose up
and the Docker compose command starts and runs your entire app. You can alternatively rundocker-compose up
using the docker-compose binary.
Compose yaml配置(一组关联的容器)
version: "3.9" # optional since v1.27.0
services: # 容器 服务应用:yaml中配置多个服务,如web、redis、mysql...
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
Compose安装
- 下载
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/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
chmod +x /usr/local/bin/docker-compose
- 授权
chmod +x /usr/local/bin/docker-compose
查看版本
安装完成!
Compose卸载
如果使用curl安装
rm /usr/local/bin/docker-compose
如果使用pip安装
pip uninstall docker-compose
使用体验
On this page you build a simple Python web application running on Docker Compose. The application uses the Flask framework and maintains a hit counter in Redis. While the sample uses Python, the concepts demonstrated here should be understandable even if you’re not familiar with it.
通过官网提供的应用程序来体验。
第一步:
- 创建项目目录
mkdir composetest
cd composetest
- 创建一个app.py文件
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
redis 是应用容器中redis容器的主机名,在同一网络下可以通过服务名访问,端口默认6379;
- 创建一个
requirements.txt
文件并写入:
flask
redis
第二步:
创建一个Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
第三步:
创建一个docker-compose.yml
配置文件
version: "3.3"
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
这个文件定义了两个服务web和redis。
第四步:
Build and run这个应用
在你的项目目录中,运行docker-compose up来启动你的应用程序。
docker-compose up
启动成功;可以看到容器命名都带有数字,是因为集群下副本数量
查看容器docker ps
,并且可以成功访问;
自动下载镜像
自动创建网络(项目中的内容都在同个网络下)
停止:
# 停止服务
docker-compose stop
# 停止服务 同时删除容器
docker-compose down
yaml规范
https://docs.docker.com/compose/compose-file/compose-file-v3/#compose-file-structure-and-examples
version: "3.9"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
max_replicas_per_node: 1
constraints:
- "node.role==manager"
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints:
- "node.role==manager"
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints:
- "node.role==manager"
networks:
frontend:
backend:
volumes:
db-data:
depends_on: 依赖关系,如下web依赖redis和db,所以通过depends_on表明关系
version: "3.9"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
===============Thanks Aliyun=================
===============THE END=================