重学Docker
<blockquote><p>转了云方向,代码都少写了</p>
</blockquote>
<br>
<br>
<h2 id="1-为什么出现docker">1. 为什么出现Docker</h2>
<p>以前开发项目有开发的环境、测试的环境、还有生产的环境,每经过一阶段就要迁移项目。不同的环境有不同的配置,可能导致不可预估的错误,运维要经常性的改动</p>
<br>
<p>世界陷入了混乱,于是上帝说,让Docker来吧,于是一切光明。Dokcer 把初始的环境一模一样地复制过来,那么就消除了协作编码时,我的机器能运行,而其他机器不能运行的困境</p>
<br>
<p>Docker是基于Go语言的开源项目,Docker可实现应用层的隔离,共享宿主机内核、而虚拟机是隔离系统,连内核,硬件都是各自模拟的</p>
<br>
<br>
<br>
<br>
<h2 id="2-docker的结构">2. Docker的结构</h2>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214422560-1471042508.png" alt="" loading="lazy"></p>
<p>Docker_Host (宿主机):安装了Docker程序的主机,形式为一个守护进程</p>
<p>Client (客户端):连接docker主机进行操作(与守护进程通信)</p>
<p>Registry (仓库):保存各种打包好的镜像(类似Github)</p>
<p>Images (镜像):软件打包好的镜像,放进仓库中(笔者理解为类,可以派生对象)</p>
<p>Containers (容器):镜像启动后的实例成为容器(笔者理解按照类创建的对象)</p>
<br>
<br>
<br>
<br>
<h2 id="3-卸载安装">3. 卸载、安装</h2>
<br>
<h3 id="31-卸载">3.1 卸载</h3>
<pre><code class="language-shell"># 卸载旧版本
$sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engin
# 卸载新版本
$ sudo rm -rf /var/lib/docker
$ sudo rm -rf /var/lib/containerd
$ yum remove docker-ce docker-ce-cli containerd.io
</code></pre>
<blockquote>
<p>主机上的镜像、容器、卷、自定义配置是不会自动删除的需要手动</p>
</blockquote>
<br>
<br>
<h3 id="32-配置docker库">3.2 配置Docker库</h3>
<pre><code class="language-shell">$ yum install -y yum-utils
$ yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
</code></pre>
<blockquote>
<p>安装yum工具包,里面包含yum-config-manager,用来设置yum配置</p>
<p>首次安装Docker需在yum中设置的Docker存储库,之后就可从Docker存储库中安装和更新</p>
</blockquote>
<br>
<br>
<h3 id="33-安装">3.3 安装</h3>
<pre><code class="language-shell">$ yum install docker-ce docker-ce-cli containerd.io
</code></pre>
<blockquote>
<p>docker-ce引擎(社区免费版)、cli(可远程连接守护进程)、containerd(提供容器管理服务)</p>
</blockquote>
<br>
<br>
<h3 id="34-启动">3.4 启动</h3>
<pre><code class="language-shell">$ systemctl start docker
$ systemctl enable docker
$ docker version # 查看版本
</code></pre>
<br>
<br>
<h3 id="35-设置镜像加速">3.5 设置镜像加速</h3>
<pre><code class="language-shell">$ vim /etc/docker/daemon.json
# 去阿里云开发平台查看自己的仓库地址
{
"registry-mirrors": ["https://XXXXXXXX.mirror.aliyuncs.com"]
}
$ systemctl daemon-reload
$ systemctl restart docker
</code></pre>
<blockquote>
<p>梯子加速你懂的 —_—</p>
</blockquote>
<br>
<br>
<br>
<br>
<h2 id="4-启动案例">4. 启动案例</h2>
<p>下面举几个例子,现在看不懂没关系,看看使用Docker有多快速</p>
<br>
<h3 id="41-hello-world">4.1 Hello-World</h3>
<pre><code class="language-shell"># 输入命令并执行
$ docker run hello-world
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214625985-1685322364.png" alt="" loading="lazy"></p>
<p>阅读运行之后的说明,里面有步骤与相关信息,对理解其原理有很大的帮助</p>
<br>
<br>
<h3 id="42-启动tomcat">4.2 启动Tomcat</h3>
<p>以前运行Tomcat,要安装设置启动jdk、tomcat,期间还需到weget、tar等命令</p>
<p>现在使用了Docker,只需几个命令</p>
<pre><code class="language-shell"># 拉取镜像,不加后面的标签默认拉取最新版
$ docker pull tomcat
# 启动容器
$ docker run -d -p 8080:8080 --name mytomcat -v /root/aria2-downloads:/usr/local/tomcat/webapps tomcat
# 访问
# 访问结果是404,因为镜像的webapps空的,意思是没有html页面给我们访问
# 其实最新的镜像将wepapps改名为webapps.dist,那么我们只需复制内容过去就可
# 不怕有解决方法,还是按着下面步骤输入:
$ docker exec -itmytomcat/bin/bash
$ cp -r webapps.dist/* webapps
$ exit
# 再次访问即可
</code></pre>
<br>
<br>
<h3 id="43-启动mysql">4.3 启动MySQL</h3>
<p>去Docker官网搜索MySQL,跟着其步骤走 MySQL的Docker地址,下面的密码设置官网也都有详细介绍</p>
<p>因为使用Navicat连接时会发生身份验证器错误,所以我们得进去容器修改验证器插件</p>
<pre><code class="language-shell"># 启动并设置密码
$ docker run -d -p 3306:3306 --name howlmysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 进入容器内部
docker exec -it containerId /bin/bash
# 登录容器内的MySQL
mysql -uroot -p 123456
# 修改身份验证插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
# 刷新权限
flush privileges;
</code></pre>
<br>
<br>
<h3 id="44-启动aria2">4.4 启动Aria2</h3>
<p>一个基于命令行的下载工具</p>
<pre><code class="language-shell"># Aria2本体
$ docker run -d \
--name aria2-pro \
--restart unless-stopped \
--log-opt max-size=1m \
-e PUID=$UID \
-e PGID=$GID \
-e UMASK_SET=022 \
-e RPC_SECRET=<secret> \
-e RPC_PORT=6800 \
-p 6800:6800 \
-e LISTEN_PORT=6888 \
-p 6888:6888 \
-p 6888:6888/udp \
-v $PWD/aria2-config:/config \
-v $PWD/aria2-downloads:/downloads \
p3terx/aria2-pro
# Web界面
$ docker run -d \
--name ariang \
--log-opt max-size=1m \
--restart unless-stopped \
-p 6880:6880 \
p3terx/ariang
</code></pre>
<br>
<br>
<h3 id="45-redis">4.5 Redis</h3>
<pre><code class="language-shell">mkdir -p /home/docker/redis/data && cat > /home/docker/redis/redis.conf <<EOF
#允许外网访问
bind 0.0.0.0
daemonize NO
protected-mode no
requirepass 123456
EOF
docker run -d \
--name redis \
-p 6379:6379 \
-v /home/docker/redis/redis.conf:/etc/redis/redis.conf \
-v /home/docker/redis/data:/data\
--restart always \
redis:7.0 \
redis-server /etc/redis/redis.conf \
--appendonly yes
</code></pre>
<br>
<br>
<br>
<br>
<h2 id="5-常用命令">5. 常用命令</h2>
<br>
<h3 id="51-帮助命令">5.1 帮助命令</h3>
<pre><code class="language-shell">$ docker version
$ docker info # 更详细信息,客户端,服务器运行状况
$ docker [命令] --help # 帮助命令
</code></pre>
<br>
<br>
<h3 id="52-镜像命令">5.2 镜像命令</h3>
<pre><code class="language-shell">$ docker pull name[:tag] # 拉镜像
$ docker rmi name|id # 删镜像
$ docker images # 列出本地镜像
$ docker search # 官网查找镜像
</code></pre>
<br>
<br>
<h3 id="53-容器命令">5.3 容器命令</h3>
<pre><code class="language-shell"># 新建并启动容器
$ docker run [可选参数] image
--name # 重命名
-d # 守护容器后台
-p # 端口映射
-v # 文件挂载
-i # 交互模式
-t # 分配一个伪终端,后面跟分配的终端 /bin/bash
-e # 环境配置
--rm # 用完就删包括卷,测试用(docker run --rm -it -p 80:80 nginx)
--restart=always # docker重启,容器也会跟着启动
# 列出正在运行的容器
$ docker ps [可选参数]
-a # 显示包括未运行的
-l # 显示最近创建的容器
-n # 显示最近创建的n个容器
-q # 只显示id
# 生命周期命令
$ docker start name|id
$ docker restart
$ docker stop
$ docker kill
$ docker rm [-f] # 强制删除运行中的容器
# 容器交互命令
$ docker exec # 在运行的容器里执行命令
$ docker exec -it id /bin/bash # 进入容器开一个新的终端,exit后不会停止容器运行
$ docker attach id # 进入正在执行的终端
$ ctrl + P + Q # 交互中容器不停止退出
$ docker exit # 交互中停止容器并退出
# 快捷操作
$ docker container prune删除所有容器
$ docker rmi $(docker images -q) 删除所有镜像
$ docker rm $(docker ps -aq)
</code></pre>
<br>
<br>
<h3 id="54-其他命令">5.4 其他命令</h3>
<pre><code class="language-shell">$ docker logs id # 查看容器的日志
$ docker top id # 查看容器里运行的进程
$ docker inspect id # 查看镜像详细信息(层、挂载目录)
$ docker cp id:容器路径 宿主机路径 # 拷贝容器文件到宿主机
$ docker cp 宿主机路径 id:容器路径 # 拷贝宿主机文件到容器
$ docker volume create|inspect|ls|prue|rm # 数据卷操作
$ docker build id # 由dockerfile生成镜像
$ docker history id # 查看镜像如何构建
$ docker save id # 备份镜像成.tar文件
$ docker load id # 加载备份镜像.tar文件,建议上传仓库
</code></pre>
<br>
<br>
<br>
<br>
<h2 id="6-dockers和虚拟机的区别">6. Dockers和虚拟机的区别</h2>
<br>
<h3 id="61--虚拟机">6.1虚拟机</h3>
<p>模拟出完整的计算机系统(Guest OS),模拟的系统都是完全隔离的,且运行在监视器(Hypervisor)中,这个监视器是软件、硬件或固件</p>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214707848-985389203.png" alt="" loading="lazy"></p>
<p>Infrastructure (基础设施):是硬件设施,理解为主机,即笔记本,云服务器</p>
<p>Host Operating System (主机操作系统):是主机的物理操作系统,即日常说的操作系统,Linxu、Windows</p>
<p>Hypervisor (虚拟机监视器):是运行在基础物理服务器和虚拟操作系统间的中间软件层,各应用和虚拟系统可共享硬件</p>
<p>Guest OS (宿主系统):虚拟的操作系统,虚拟机内部运行的操作系统,有完整的硬件和内核(Docker是共享)</p>
<p>Bins/Libs (命令/资源):二进制命令和资源库</p>
<p>APP (应用程序):用户安装的程序</p>
<br>
<blockquote>
<p>缺点:要运行几个隔离的应用,就要监视器启动几个宿主系统,也就是几个虚拟机。虚拟机模拟了多个隔离的系统,占用了很多的硬盘、CPU、内存,所以启动也很缓慢。</p>
</blockquote>
<br>
<br>
<h3 id="62-docker">6.2 Docker</h3>
<p>Docker是运行容器的引擎,我们将 操作系统的基础库文件、应用程序、所需的依赖等打包到镜像中,然后通过镜像创建容器(类和对象),而容器就在Docker中运行</p>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214742558-953298347.webp" alt="" loading="lazy"></p>
<p>Docker Daemon (守护进程):守护进程取代Hypervisor,是个进程,负责管理Docker容器</p>
<br>
<blockquote>
<p>守护进程与宿主机通信,为容器分配资源</p>
<p>使用宿主机的硬件资源,无需虚拟化硬件资源,所以容器无需加载内核,因此是秒级</p>
<p>Docker使用了cgroup + namespace,前者限制资源集,后者限制可访问权限</p>
<p>Docker是Client-Server结构,守护进程在宿主机上,客户端socket连接进程管理运行在主机上的容器</p>
</blockquote>
<br>
<br>
<h3 id="63-对比">6.3 对比</h3>
<p>虚拟机:彻底隔离整个运行环境,每个运行的虚拟系统都是完全隔离的</p>
<p>Docker:隔离不同的应用程序,比如数据库,后端,前端等</p>
<br>
<table>
<thead>
<tr>
<th style="text-align: center">比对项</th>
<th style="text-align: center">Container(容器)</th>
<th style="text-align: center">VM(虚拟机)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">启动速度</td>
<td style="text-align: center">秒级</td>
<td style="text-align: center">分钟级</td>
</tr>
<tr>
<td style="text-align: center">运行性能</td>
<td style="text-align: center">接近原生</td>
<td style="text-align: center">有所损失</td>
</tr>
<tr>
<td style="text-align: center">磁盘占用</td>
<td style="text-align: center">MB</td>
<td style="text-align: center">GB</td>
</tr>
<tr>
<td style="text-align: center">数量</td>
<td style="text-align: center">成百上千</td>
<td style="text-align: center">一般几十台</td>
</tr>
<tr>
<td style="text-align: center">隔离性</td>
<td style="text-align: center">进程级别</td>
<td style="text-align: center">系统级别</td>
</tr>
<tr>
<td style="text-align: center">操作系统</td>
<td style="text-align: center">只支持Linux</td>
<td style="text-align: center">几乎所有</td>
</tr>
<tr>
<td style="text-align: center">封装程度</td>
<td style="text-align: center">只打包项目代码和依赖关系,共享宿主机内核</td>
<td style="text-align: center">完整的操作系统</td>
</tr>
</tbody>
</table>
<br>
<br>
<br>
<br>
<h2 id="7-图形化界面">7. 图形化界面</h2>
<p>笔者了解到的图形化管理工具是Portainer,也是在Docker上运行的程序,建议跟着仓库文档走</p>
<pre><code class="language-shell"># 必须挂载
$ docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
</code></pre>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214919536-1705824405.png" alt="" loading="lazy"></p>
<blockquote>
<p>具体各位去摸索一下把~</p>
</blockquote>
<br>
<br>
<br>
<br>
<h2 id="8-镜像-image">8. 镜像 image</h2>
<p>镜像一种轻量级、可执行的独立软件包,用来打包软件的运行环境和基于运行环境开发的技术。它包含运行某个软件需要的所有内容(包括代码、运行库、环境变量和配置文件)</p>
<br>
<h3 id="81-联合文件系统">8.1 联合文件系统</h3>
<p>联合文件系统(UnionFS):是一个分层的、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层叠加(类似Git),同时可以将不同目录挂载到同一虚拟文件系统下(-v 文件挂载)</p>
<br>
<p>UnionFS是Docker镜像的基础,镜像可以通过分层来进行继承(分层可以共用),基于基础镜像可以制作各种具体的应用镜像</p>
<blockquote>
<p>一次同时加载多个文件系统,但从外面看只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有的底层文件和目录</p>
</blockquote>
<br>
<h3 id="82-镜像加载原理">8.2 镜像加载原理</h3>
<p>Docker使用UnionFS进行分层,底层是bootfs文件系统(bootloader加载最基础的内核、kernvel)</p>
<p>bootfs的上一层是rootfs,也就是 /dev,/bin,/etc等标准目录和文件</p>
<blockquote>
<p>不同的镜像中有相同的分层,那宿主机只需在磁盘、内存中保存一份,这些镜像共享这些分层</p>
</blockquote>
<br>
<br>
<h3 id="83-镜像层的叠加">8.3 镜像层的叠加</h3>
<p>假如我们在Docker上安装tomcat,首先底层是bootfs层,然后在上面安装centos (rootfs),意思是修改了文件系统,那就会叠加一层文件系统、依次类推,还有jdk8层、tomcat层。最终打包成tomcat这个镜像,对外则是一个整体</p>
<p><img src="https://img2020.cnblogs.com/blog/1737887/202107/1737887-20210714214942044-336229572.png" alt="" loading="lazy"></p>
<blockquote>
<p>镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部(容器层,之下叫镜像层)</p>
<p>若我们在容器层删除了文件,那么会生成一个wihteout文件,将对应的下层文件隐藏掉</p>
</blockquote>
<br>
<br>
<h3 id="84-提交生成镜像">8.4 提交生成镜像</h3>
<p>上面tomcat的案例我们已经修改过webapps的内容,因修改了联合文件系统,所以可作为一次提交来层层叠加</p>
<pre><code class="language-shell"># 提交到本地仓库,没有add行为了
# name[:tag] 是 自己命名的 镜像名 作为镜像名
$ docker commit -m "提交信息" -a "作者" id name[:tag]
# eg:
$ docker commit -m "add webapps files" -a "Howl" 9c8524bxxxxmytomcat:1.0
# 然后就可看到自己打包的镜像了
$ docker images
</code></pre>
<br>
<br>
<br>
<br>
<h2 id="9-数据卷">9. 数据卷</h2>
<p>数据卷(volume)是由docker挂载到容器(不属于UFS)存在于一个或多个容器中的目录或文件,因此能绕过UFS一些用于持续存储或共享数据的特性</p>
<br>
<p>卷的出现是为了数据的持久化和同步操作,其完全独立于容器的生存周期,因此在删除容器时其挂载的数据卷不会被删除。<strong>简单来说:</strong>使容器和宿主机共享独立于docker生命周期的数据、<strong>亦或者:</strong>独立于docker生命周期的目录挂载</p>
<br>
<p><strong>特点:</strong></p>
<ul>
<li>数据卷可以容器之间共享或重用</li>
<li>卷中的更改直接生效</li>
<li>卷中的更改不会包含在镜像的更新中</li>
<li>数据卷的生命周期持续到没有容器使用为止</li>
</ul>
<br>
<br>
<h3 id="91-具名匿名挂载">9.1 具名、匿名挂载</h3>
<p>数据卷的默认地址 <code>/var/lib/docker/volumes/xxx</code></p>
<pre><code class="language-shell">$ docker run -v /宿主机绝对路径:/容器内目录 name # 具名挂载(不加"/",在默认地址下起个名字而已)
$ docker run -v /容器内目录 name # 匿名挂载,宿主机用默认地址(会生成唯一的32位id)
# 还有只读,读写权限
$ docker run -v /宿主机绝对路径:/容器内目录:ro|rw name
# 还有先创建数据卷,后面再挂载
$ docker volume create mysql_data
$ docker run -d -p 3306:3360 -v mysql_data:/root/mysql_data
</code></pre>
<br>
<br>
<h3 id="92-dockerfile挂载">9.2 Dockerfile挂载</h3>
<p>这里说明有这种挂载方式,什么是dockerfile下面会讲</p>
<pre><code class="language-shell">$ FROM centos
# 没有"/",是匿名挂载,宿主机的默认地址
# 容器内直接在根目录下
$ VOLUME ["volume01","volume02"]
$ CMD echo "----Howl write dockerfile----"
$ CMD /bin/bash
</code></pre>
<br>
<br>
<h3 id="93-容器数据卷">9.3 容器数据卷</h3>
<p>容器数据卷是用于容器间的数据共享,操作方式还是命令行: <code>--volume-from</code></p>
<pre><code class="language-shell"># centos01就叫数据卷容器
$ docker run -d --name centos01 howl/centos:1.0
$ docker run -d --name centos02 --volume-from centos01 howl/centos:1.0
</code></pre>
<blockquote>
<p>这是数据卷,不和容器同生命周期,所以哪怕父容器删了,其余容器也能访问同步</p>
</blockquote>
<br>
<br>
<br>
<br>
<h2 id="10-dockerfile">10. Dockerfile</h2>
<p>Dockerfile是有一系列命令和参数的脚本,通过这个脚本我们可以构建一个镜像</p>
<br>
<h3 id="101-dockerfile指令">10.1 Dockerfile指令</h3>
<p>指令必须都是大写,从上往下执行,且每个指令都会创建一层(可用<code>&&</code>将命令连起来只生成一层)</p>
<table>
<thead>
<tr>
<th>命令</th>
<th>语法</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>FROM</td>
<td>FROM image[:tag]</td>
<td>指定基础镜像,必须第一条。FROM scratch表示不以任何镜像为基础</td>
</tr>
<tr>
<td>MAINTAINER</td>
<td></td>
<td>维护者信息</td>
</tr>
<tr>
<td>RUN</td>
<td></td>
<td>镜像构建时需要执行的命令</td>
</tr>
<tr>
<td>ADD</td>
<td></td>
<td>复制本地压缩文件,会自动解压</td>
</tr>
<tr>
<td>WORKDIR</td>
<td></td>
<td>镜像工作目录</td>
</tr>
<tr>
<td>VOLUME</td>
<td></td>
<td>设置容器卷</td>
</tr>
<tr>
<td>EXPOSE</td>
<td></td>
<td>指定堆外端口</td>
</tr>
<tr>
<td>CMD</td>
<td></td>
<td>指定容器运行中的命令,会被覆盖</td>
</tr>
<tr>
<td>ENTRYPOINT</td>
<td></td>
<td>指定容器启动时运行的命令,可以追加命令</td>
</tr>
<tr>
<td>ONBUILD</td>
<td></td>
<td>当构建一个被继承Dockerfile时会运行该指令</td>
</tr>
<tr>
<td>COPY</td>
<td>COPY 宿主文件地址 容器文件地址</td>
<td>将文件拷贝到镜像中</td>
</tr>
<tr>
<td>ENV</td>
<td></td>
<td>构建时设置环境变量</td>
</tr>
</tbody>
</table>
<br>
<br>
<h3 id="101-编写dockerfile">10.1 编写Dockerfile</h3>
<p>举例做个tomcat镜像,需要准备tomcat压缩包、jdk压缩包、readme文件</p>
<pre><code class="language-shell">$ FROM centos
$ MAINTAINER howl
$ COPY readme.txt /usr/local/readme.txt
$ ADD jdk-8u291-linux-x64.tar.gz /usr/local
$ ADD apache-tomcat-8.5.68.tar.gz /usr/local
$ RUN yum -y install vim
$ ENV MYPATH /usr/local
$ WORKDIR $MYPATH
# JAVA_HOME 目录安装之后才知道
$ ENV JAVA_HOME /usr/local/jdk1.8.0_291
$ ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
$ ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.68
$ ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.68
$ ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib
$ EXPOSE 8080
$ CMD /usr/local/apache-tomcat-8.5.68/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.68/bin/logs/catalina.out
</code></pre>
<blockquote>
<p>每条指令都会创建一个新的镜像层,并对镜像进行提交</p>
<p>若构建名为Dockerfile那么就会自动查找,不用-f去指定了</p>
<p>Docker运行得有前台应用在运行,不然会自动结束,tail就是为了前台运行,比如top等命令</p>
<p>注意:根据linux位数,arm,aarch64来安装jdk,笔者安装错了,走了很多弯路</p>
</blockquote>
<br>
<br>
<h3 id="102-build制作镜像">10.2 Build制作镜像</h3>
<pre><code class="language-shell"># -f 指定dockerfile的路径
# -t 生成的镜像名字[:tag] 生成镜像的地址
# . 表示当前目录
$ docker build -t howl/tomcat .
</code></pre>
<br>
<br>
<h3 id="103-运行制作的镜像">10.3 运行制作的镜像</h3>
<pre><code class="language-shell">$ docker run -d -p 8080:8080 howl/tomcat
</code></pre>
<blockquote>
<p>有个注意的地方,webapps下要新建目录才能访问的,不能放入已有文件夹内,也不能直接放入webapps里面</p>
</blockquote>
<br>
<br>
<h3 id="104-发布镜像">10.4 发布镜像</h3>
<p>镜像的发布有两种途径,分别是:</p>
<br>
<ul>
<li><strong>DockerHub</strong></li>
</ul>
<pre><code class="language-shell"># 首先需要登录
$ docker login -u loadingkiller
$ Password: "输入密码"
# 推送名字得是自己DockerHub上的账号名,所以得先改标签
# 本来 howl/centos 改成 loadingkiller/tomcat
$ docker tag howl/tomcat:latest loadingkiller/tomcat:1.0
# 推送,速度慢等吧
$ docker push loadingkiller/centos:1.0
</code></pre>
<br>
<ul>
<li><strong>阿里云镜像仓库</strong></li>
</ul>
<p>进入阿里云镜像管理可以创建镜像仓库,然后跟着里面的提示走</p>
<pre><code class="language-shell"># 登录
docker login -u=XXX registry.cn-hongkong.aliyuncs.com
# 选择分支对应关系
docker tag registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]
# 推送上去
docker push registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]
# 拉取
docker pull registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]
</code></pre>
<br>
<br>
<br>
<br><br><br>
来源:https://www.cnblogs.com/Howlet/p/15013163.html
頁:
[1]