传送门:官方参考文档 | Docker Hub镜像仓库 | 【狂神说Java】Docker视频教程
Docker 是一个便携的应用容器,基于 Go 语言开发的。它可以让开发者打包应用以及应用的依赖到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。容器是完全使用沙箱机制,相互之间不会有任何接口,非常适合于高密度环境以及中小型部署,而且可以用更少的资源做更多的事情。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。
Docker 提供了一个基础系统镜像作为运行应用的基础。Docker 并不在乎你的应用程序是什么、做什么,也就是说,只要是 Linux 系统上的应用都可以运行在 Docker 容器中。这是因为 Docker 提供了一组应用打包、传输和部署的方法,以便你能更好地在容器内运行任何应用。
例如:Docker 只需要一条命令便可以运行 MySQL 数据库:
[root@localhost ~]# docker run -d -p 3306:3306 tutum/mysql
DevOps思想:它涵盖开发、测试、运维的整个过程,其核心就是流程的统一和自动化。
镜像(Image): Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务。一个镜像可以创建多个容器。比如,Tomcat镜像 ===> Run ===> Tomcat容器(可以提供服务)
容器(Containers): Docker利用容器技术,可以独立运行一个或一组应用,它是通过镜像来创建的。我们可以把容器理解为就是一个微型的Linux系统。它包括启动、停止、删除等基本命令。
仓库(Repository): 就是存放镜像的地方,一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。官方默认的Registry是 Docker Hub,在国内使用时一般需要配置镜像加速。
注意:在CentOS系统上安装Docker引擎时,要求操作系统是CentOS 7以上版本。可以通过如下命令查看系统内核与系统版本。
# 系统内核版本
[root@localhost ~]# uname -r
# 查看系统版本
[root@localhost ~]# cat /etc/os-release
卸载旧版本
如果安装了这些,请卸载它们以及相关的依赖项
[root@localhost ~]# yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
添加Docker的yum源信息
# 安装 yum-utils
[root@localhost ~]# yum install -y yum-utils
# (推荐)使用阿里云的软件源地址
[root@localhost ~]# yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# (不推荐)国外地址
[root@localhost ~]# yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
小贴士: yum-utils
提供了 yum-config-manager
的实用程序
安装前建议更新 yum 软件包索引
[root@localhost ~]# yum makecache fast
小贴士:该操作的目的就是将软件包信息提前在本地缓存一份,用来提高搜索安装软件的速度。如果觉得 yum 下载的软件包占用磁盘空间,可以使用 yum clean [all / 软件包]
指令清除缓存。
安装docker相关的配置
[root@localhost ~]# yum install docker-ce docker-ce-cli containerd.io
小贴士:docker-ce 是社区版,docker-ee 企业版
启动 Docker 并设置开机启动
# 启动 Docker
[root@localhost ~]# systemctl start docker
# 查看当前版本号,是否启动成功
[root@localhost ~]# docker version
# 设置开机自启动
[root@localhost ~]# systemctl enable docker
运行 hello-world 看看效果
# 运行hello-world
[root@localhost ~]# docker run hello-world
# 查看下载的 hello-world 镜像
[root@localhost ~]# docker images
Docker卸载
# 1. 卸载依赖
[root@localhost ~]# yum remove docker-ce docker-ce-cli containerd.io
# 2. 删除资源 /var/lib/docker 是 Docker 的默认工作路径
[root@localhost ~]# rm -rf /var/lib/docker
小贴士:Docker官方的安装文档也比较详细,有需要的小伙伴可以查阅 官方安装文档(CentOS)
使用加速器可以提升获取Docker官方镜像的速度,在不同的操作系统下,配置加速器的方式略有不同,下文将介绍主要操作系统的配置方法。
获取加速器的地址
您登录容器镜像服务控制台后,在左侧导航栏选择镜像工具 > 镜像加速器,在镜像加速器页面就会显示为您独立分配的加速器地址。
例如:
加速器地址:[系统分配前缀].mirror.aliyuncs.com
配置加速器
当您安装的Docker Version不低于1.10时,建议直接通过daemon config进行配置。使用配置文件 /etc/docker/daemon.json
(没有时新建该文件)。
{
"registry-mirrors": ["" ]
}
重启Docker Daemon即可
[root@localhost ~]# sudo systemctl daemon-reload
[root@localhost ~]# sudo systemctl restart docker
小贴士:阿里云官方也提供了更加详细的说明文档,有需要的小伙伴可以查阅 阿里云官方帮助文档
Docker是一个 Client - Server 结构的系统,因此它提供了在客户端 - 服务器环境中进行交互和工作的命令。在这里,我们列出了一些重要和常用的 Docker 命令进行学习。
查看Docker的版本信息
[root@localhost ~]# docker version
查看Docker的系统信息,包括镜像和容器的数量
[root@localhost ~]# docker info
帮助命令(可查看可选的参数)
[root@localhost ~]# docker 命令 --help
docker images
查看本地主机的所有镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 2 months ago 13.3kB
# 可选参数
-a,--all # 列出所有镜像
-q,--quiet # 只显示镜像的id
docker search
搜索镜像
搜索镜像时建议优先使用 官网镜像仓库 ,那里有完善的文档信息。
[root@localhost ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11833 [OK]
mariadb MariaDB Server is a high performing open sou… 4505 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 887 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 92
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 90
# 可选参数
-f, --filter filter # 根据所提供的条件过滤输出 如:docker search mysql --filter STARS=5000
--format string # 输出打印模板,如:docker search --format "{{.Name}}: {{.StarCount}}" nginx
--limit int # 最大搜索结果数(默认为25)
--no-trunc # 不截断输出
docker pull 镜像名[:tag]
下载镜像
[root@localhost ~]# docker pull mysql
Using default tag: latest # 如果下载命令中部指定tag,则默认下载latest
latest: Pulling from library/mysql
ffbb094f4f9e: Pull complete # 分层下载,docker image的核心-联合文件系统
df186527fc46: Pull complete
fa362a6aa7bd: Pull complete
5af7cb1a200e: Pull complete
949da226cc6d: Pull complete
bce007079ee9: Pull complete
eab9f076e5a3: Pull complete
8a57a7529e8d: Pull complete
b1ccc6ed6fc7: Pull complete
b4af75e64169: Pull complete
3aed6a9cd681: Pull complete
23390142f76f: Pull complete
Digest: sha256:ff9a288d1ecf4397967989b5d1ec269f7d9042a46fc8bc2c3ae35458c1a26727
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 下载来源的真实地址
# 如下两个命令是等价的
[root@localhost ~]# docker pull mysql
[root@localhost ~]# docker pull docker.io/library/mysql:latest
# 下载指定版本试一试
[root@localhost ~]# docker pull mysql:5.7
docker rmi 删除镜像
# 删除指定的镜像
[root@localhost ~]# docker rmi -f 镜像id
# 删除多个镜像
[root@localhost ~]# docker rmi -f 镜像id 镜像id 镜像id
# 删除全部的镜像
[root@localhost ~]# docker rmi -f $(docker images -aq)
# 可选参数
-f, --force # 强制移除
--no-prune # 不移除该镜像的过程镜像,默认移除
如拉取一个 centos 镜像
[root@localhost ~]# docker pull centos
运行容器并进入容器
[root@localhost ~]# docker run --name CentOS -it centos /bin/bash
[root@d6cbf0e93a8b /]# ls # 进入到centos容器中,展示根目录下的文件
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 重要参数说明
--name string # 指定容器名字
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口及主机端口映射,三种示例如下
-p ip:主机端口:容器端口
-p 主机端口:容器端口 # 推荐
-p 容器端口
-P # 随机指定端口(大写的P)
小贴士: docker run -it centos /bin/bash
命令后面的 bin/bash
的作用,表示载入容器后运行bash ,Docker中必须要保持一个进程的运行,要不然整个容器启动后就会马上停止,这个 /bin/bash
就表示启动容器后启动 bash。
后台方式运行容器
# 后台方式运行 centos 容器,因为没有前台进程使用,会马上停止运行
[root@localhost ~]# docker run --name CentOS_01 -d centos
ecbc3e9d773d120ba0cc14ba064cc9eeb843cd23bab81b1fb9724f045319874d
[root@localhost ~]# docker ps -n 1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ecbc3e9d773d centos "/bin/bash" About a minute ago Exited (0) About a minute ago CentOS_01
# 运行一个脚本,使得 centos 容器保持运行状态
[root@localhost ~]# docker run --name CentOS_02 -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
[root@localhost ~]# docker ps -n 1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67a894effbcf centos "/bin/sh -c 'while t…" 4 seconds ago Up 3 seconds CentOS_02
# 查看容器的日志信息
[root@localhost ~]# docker logs -tf --tail 3 67a894effbcf
2021-12-17T15:03:36.016984749Z hi
2021-12-17T15:03:41.030581591Z hi
2021-12-17T15:03:46.037004793Z hi
2021-12-17T15:03:51.045708743Z hi
小贴士:Docker容器后台运行时,必须要有一个前台的进程,否则会自动停止。
退出容器
# exit 停止并退出容器(以后台方式运行时,则仅退出容器)
# Ctrl+P+Q 不停止容器退出
[root@d6cbf0e93a8b /]# exit
exit
[root@localhost ~]#
列出系统中的容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6cbf0e93a8b centos "/bin/bash" 30 seconds ago Up 28 seconds CentOS
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6cbf0e93a8b centos "/bin/bash" 34 seconds ago Up 32 seconds CentOS
54f01f55548d feb5d9fea6a5 "/hello" 7 hours ago Exited (0) 7 hours ago friendly_chandrasekhar
# 可选参数,不带参数默认列出当前正在运行的容器
-a # 列出所有容器的运行记录
-n=? # 显示最近创建的n个容器
-q # 只显示容器的编号
删除容器
[root@localhost ~]# docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
[root@localhost ~]# docker rm -f $(docker ps -aq) # 删除所有的容器
[root@localhost ~]# docker ps -a -q|xargs docker rm # 删除所有的容器
启动和停止容器
[root@localhost ~]# docker start 容器id # 启动容器
[root@localhost ~]# docker restart 容器id # 重启容器
[root@localhost ~]# docker stop 容器id # 停止当前运行的容器
[root@localhost ~]# docker kill 容器id # 强制停止当前容器
日志的查看
[root@localhost ~]# docker logs -tf 容器id
[root@localhost ~]# docker logs --tail number 容器id # 注意:number为要显示的日志条数
查看容器中进程信息
[root@localhost ~]# docker top d6cbf0e93a8b
UID PID PPID C STIME TTY TIME CMD
root 3825 3806 0 22:43 pts/0 00:00:00 /bin/bash
查看容器的元数据
[root@localhost ~]# docker inspect d6cbf0e93a8b
进入当前正在运行的容器
因为通常我们的容器都是使用后台方式来运行的,有时需要进入容器修改配置信息
方式一(推荐): docker exec
进入容器后开启一个新的终端,可以在里面操作,使用 exit
退出时,不会停止容器运行
[root@localhost ~]# docker exec -it d6cbf0e93a8b /bin/bash
[root@d6cbf0e93a8b /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@d6cbf0e93a8b /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 14:43 pts/0 00:00:00 /bin/bash
root 23 0 0 15:12 pts/1 00:00:00 /bin/bash
root 38 23 0 15:12 pts/1 00:00:00 ps -ef
[root@d6cbf0e93a8b /]# exit
exit
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6cbf0e93a8b centos "/bin/bash" 31 minutes ago Up 31 minutes CentOS
方式二(不推荐): docker attach
进入容器正在执行的终端,不会启动新的进程,使用 exit
退出时,会停止容器运行
[root@localhost ~]# docker attach d6cbf0e93a8b
[root@d6cbf0e93a8b /]# exit
exit
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
拷贝操作
# 拷贝容器的文件到主机中
docker cp 容器id:容器内路径 目的主机路径
# 拷贝宿主机的文件到容器中
docker cp 目的主机路径 容器id:容器内路径
Docker有很多操作(Docker CLI 的基础命令),我们没必要记住所有命令的具体使用方法。学习方法,我们可以通过命令 docker command --help
更深入的了解指定的 Docker 命令使用方法。例如:我们要查看 docker images
指令的具体使用方法:
[root@localhost ~]# docker images --help
利用前面学习到的技术部署容器,容器运行所需的配置信息和数据文件都是保存在该容器中的。这就会导致容器被删除后,容器中产生的数据也就没有了。那怎么才能做到容器数据的持久化呢?
使用下面介绍的数据卷技术就可以做到容器之间数据的共享和容器与本地之间的持久化存储。
方式一:直接使用命令参数来挂载
命令: docker run -it -v 宿主机目录:容器目录
实战:安装MySQL
# 安装MySQL数据库,设置密码为123456,并挂载两个数据卷用于存储配置和数据信息
[root@localhost ~]# docker run --name MySQL -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /home/mysql/conf:/etc/mysql/conf \
-v /home/mysql/data:/var/lib/mysql \
mysql:5.7
# 此时可以通过数据库可视化工具连接到MySQL,并尝试创建一下数据表
# 删除MySQL容器
[root@localhost ~]# docker rm -f MySQL
# 执行执行数据库安装后,之前MySQL中的创建的数据表依然存在
执行数据卷挂载以后,我们可以通过 docker inspect 容器名
命令,在元数据信息中查看数据卷情况,结果如下:
当然也可以通过 docker volume inspect 数据卷名
命令,查看数据卷挂载情况。如下:
方式二:使用Dockerfile脚本挂载数据卷
初识 Dockerfile ,使用 Dockerfile 中的 VOLUME 指令来给镜像添加一个或多个数据卷。 Dockerfile 脚本比较简单,按照如下步骤操作即可:
# 编写 Dockerfile 脚本
[root@localhost home]# vi dockerfile01
# 脚本内容
# 每个指令必须是大写字母,一个指令代表一个新的镜像层
FROM centos # FROM:基础镜像,一切基于这个开始构建
VOLUME ["volume01","volume02"] # VOLUME:挂载的目录
CMD echo "----end----" # CMD:容器启动时要运行的命令
CMD /bin/bash
# 执行构建镜像
[root@localhost home]# docker build -f dockerfile01 -t wangxf/centos:1.0 .
# 查看镜像
[root@localhost home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wangxf/centos 1.0 af2f08491630 22 seconds ago 231MB
# 启动自己生成的容器
[root@localhost home]# docker run -it af2f08491630 /bin/bash
[root@c60faa5b4dea /]# ls v
var/ volume01/ volume02/
# 解析:上面的volume01 volume02两个目录就是刚刚通过Dockerfile挂载的数据卷,自己动手找一下他们分别挂载到宿主机的什么位置呢?
匿名挂载
# 匿名挂载:-v 容器内路径
[root@localhost data]# docker run -d -p 80:80 --name Nginx -v /ect/nginx nginx
具名挂载
# 具名挂载:-v 卷名:容器内路径
[root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx nginx
# 查看卷情况
[root@localhost data]# docker volume ls
DRIVER VOLUME NAME
local 40104546065ec402615d03842c6b7d6cbdb8e43413666c697ea4980baaa36477
local cd637459e5acab02e1935d098a916d873727f0f83d0377dc7caf17be5c170fb0
local juming-nginx
# 查看具名卷在配置路径
[root@localhost data]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2021-12-18T18:45:24+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
小贴士:所有的Docker容器内的卷,在没有指定目录的情况下都是在 /var/lib/docker/volumes/卷名称/_data/
路径下
在 -v 可选参数后面追加 :ro
/ :rw
,可以改变读写权限。
:ro,readonly即只读权限,说明这个路径只能通过宿主机来操作,容器内部是无法操作的
:rw,readwrite即可读可写权限,默认就是它
# 一旦设置了容器权限,容器对我们挂载出来的内容就是限定的了
[root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx:ro nginx
[root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx:rw nginx
通过容器数据卷就可以实现同步多个容器间的数据。
实操示例:下面我们在创建两个 centos 容器,并对两个容器建立数据卷共享关系。
新创建一个 centos_01 容器,并进行指定路径挂载
[root@localhost ~]# docker run -it --name centos_01 -v /webapp:/webapp centos
# 此时在 centos_01 容器或者宿主机容器的 /webapp 目录新建文件,两者都会自动同步
通过 --volumes-from
可选参数,与 centos_01 容器建立容器数据卷挂载关系
[root@localhost ~]# docker run -it --name centos_02 --volumes-from centos_01 centos
# 创建好 centos_02 容器以后,发现 /webapp 目录中的内容与 centos_01 容器、宿主机容器中的 /webapp 目录的内容相同
删除 centos_01 容器,然后进入 centos_02 看看数据卷中的内容还是否存在
[root@localhost volumes]# docker rm -f centos_01
[root@localhost volumes]# docker exec -it centos_02 /bin/bash
[root@3c9e9153aa30 /]# cd /webapp/ && ls
wangxf.java
容器之间数据卷的生命周期一直持续到没有容器使用为止。但是如果你的数据卷中的数据持久化到本地后,本地数据是不会删除的。
Dockerfile就是用来构建Docker镜像的脚本文件,实际上就是一个命令脚本。通过这个脚本就可以生成镜像,镜像是一层一层的,那么脚本中的每个命令都是一层。
Dockerfile是面向开发者的,发布项目时需要做成镜像,那么就需要编写 Dockerfile 脚本文件。涉及如下几个关键点:
docker build
命令构建成一个镜像docker run
命令运行镜像docker push
发布镜像到镜像仓库(DockerHub、阿里云镜像仓库)指令说明
FROM # 指定基础镜像,一切都要基于这个开始
MAINTAINER # 镜像是谁写的,姓名+邮箱(通用标准)
RUN # 镜像构建时需要运行的命令
ADD # 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 对外暴露的端口
CMD # 指定这个容器启动的时候要运行的命令(只有最后一个会生效)
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令,触发指令
COPY # 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
ENV # 构建的时候设置环境变量
实操练习,实现一个自己的 centos 容器
首先编写一个 Dockerfile 脚本文件,内容如下:
[root@localhost dockerfile]# vim mydockerfile-centos
FROM centos
MAINTAINER wangxf<912309845@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim # 安装vim工具
RUN yum -y install net-tools # 安装网络基础包
EXPOSE 80
CMD echo $MYPATH
CMD echo "--- END ---"
CMD /bin/bash
通过 Dockerfile 脚本构建镜像文件
命令: docker build -f dockerfile文件路径 -t 镜像名:[TAG] .
,注意最后的点
[root@localhost dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
[root@localhost dockerfile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 0.1 9f12990cd386 20 seconds ago 322MB
修改镜像TAG
[root@localhost dockerfile]# docker tag 9f12990cd386 mycentos:0.2
测试运行
# 运行容器
[root@localhost dockerfile]# docker run -it mycentos:0.1
# 运行容器后,自动进入到 /usr/local 目录
[root@6eb7f871b213 local]# pwd
/usr/local
# 看看我们安装的网络基础包是否生效了
[root@6eb7f871b213 local]# ifconfig
eth0: flags=4163,BROADCAST,RUNNING,MULTICAST> mtu 1500
其他内容省略……
查看镜像的变更历史
[root@localhost dockerfile]# docker history 9f12990cd386
IMAGE CREATED CREATED BY SIZE COMMENT
9f12990cd386 14 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
7e99c710a5d5 14 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
ae48ddb633e8 14 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
7079d2482219 14 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
5e2d68b08b92 14 minutes ago /bin/sh -c yum -y install net-tools 27MB
ecf92b08e7bf 14 minutes ago /bin/sh -c yum -y install vim 64.1MB
63e10164af59 15 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
1910d234fba0 15 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
a7f48ed49a91 15 minutes ago /bin/sh -c #(nop) MAINTAINER wangxf<9123098… 0B
5d0da3dc9764 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
3 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
3 months ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB
准备镜像文件,Tomcat压缩包,JDK压缩包
# 为了跳过Oracle对其资源的下载限制,JDK下载需要设置请求头信息
[root@localhost dockerfile]# wget --no-check-certificate -c --header="Cookie: oraclelicense=accept-securebackup-cookie" \
http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
# Tomcat下载
[root@localhost dockerfile]# wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.23/bin/apache-tomcat-8.0.23.tar.gz
[root@localhost dockerfile]# ls
apache-tomcat-8.0.23.tar.gz jdk-8u131-linux-x64.tar.gz
编写 Dockerfile 脚本文件,文件名建议使用官方命名:Dockerfile ,这样在 docker build 时会默认寻找当前目录下的文件,不需要使用 -f 参数进行指定了。
FROM centos
MAINTAINER wangxf<912309845@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u311-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.0.23.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_311
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.0.23
ENV CATALINA_BASH /usr/local/apache-tomcat-8.0.23
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.0.23/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.0.23/logs/catalina.out
构建镜像
[root@localhost dockerfile]# docker build -t diytomcat:1.0 .
启动镜像
[root@localhost dockerfile]# docker run -d -p 9090:8080 --name diytomcat \
-v /home/dockerfile/tomcat/webapps/test:/usr/local/apache-tomcat-8.0.23/webapps/test \
-v /home/dockerfile/tomcat/logs:/usr/local/apache-tomcat-8.0.23/logs \
diytomcat:1.0
测试访问:http://your_ip:9090/
发布项目,我们在本地挂载的数据卷中进行项目发布,发布后访问http://your_ip:9090/test
[root@localhost dockerfile]# cd /home/dockerfile/tomcat/webapps/test
[root@localhost test]# cat index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
"utf-8">
Hello World</title>
</head>
Hello World!
<% out.println("你的 IP 地址 " + request.getRemoteAddr()); %>
</body>
</html>
参考官方文档:容器镜像服务
安装Docker的时候,它会自动创建四个网络:bridge(创建容器默认连接到此网络),host,container,none。在Docker 1.9版本以后新增了用户自定义网络模式
--net=bridge
),这是Dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。 在 docker run 启动容器的时候,如果不加 --net 参数,就默认采用这种网络模式。安装完 Docker,系统会自动添加一个供 Docker 使用的网桥 docker0,我们创建一个新的容器时, 容器通过 DHCP 获取一个与 docker0 同网段的IP地址,并默认连接到 docker0 网桥,以此实现容器与宿主机的网络互通。--net=host
), 这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。 将不拥有自己独立的 Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。--net=container:name OR id
), 与host模式类似,只是容器将与指定的容器共享网络命名空间。 这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。--net=none
), 为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。 这个模式下,Dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。安装 Docker 以后,宿主机会自动配置一个虚拟的网桥叫 docker0,并且 Docker 会在私有 IP 网段中,选择一个和宿主机不同的IP地址和子网分配给 docker0,例如将 172.17.0.1/16 分配给 docker0 网桥 。
一般情况下,使用 Docker 创建一个容器的时候,都会自动创建一对虚拟的网络接口(叫做veth-pair),分别放在宿主机和新容器中,这就是连接各种虚拟网络设备的桥梁。宿主机一端的虚拟接口(即veth)会连接到 docker0 网桥上;而容器一端的虚拟接口(即eth0)只能在该容器内可见,并且会从网桥可用地址段中获取一个空闲地址分配给该容器(例如172.17.0.2/16)。通过这种方式,宿主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在宿主机和所有容器之间一个虚拟共享网络。当然用户也可以通过 docker network 命令来手动管理网络。
docker0 可以通过宿主机的 ip addr
命令进行查看:
Docker中的网络接口默认都是虚拟的接口。虚拟接口的最大优势就是转发效率极高。这是因为Linux在内核中通过数据复制实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。需要注意的是,当我们删除一个容器后,该容器对应的虚拟网络接口也会随之删除。
在微服务部署的场景下,注册中心是使用服务名来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动,所以我们需要使用容器名来配置容器间的网络连接。使用 --link 可以实现这个功能。
–link
使用 --link 实现容器互联
# 启动 tomcat01
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat:8.0.20
# 启动 tomcat02,通过 --link 连接到 tomcat01
[root@localhost ~]# docker run -d -P --name tomcat02 --link tomcat01 tomcat:8.0.20
# 进入tomcat02,ping tomcat01
[root@localhost ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (172.17.0.1) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.1) : icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from tomcat01 (172.17.0.1) : icmp_seq=2 ttl=64 time=0.037 ms
64 bytes from tomcat01 (172.17.0.1) : icmp_seq=3 ttl=64 time=0.039 ms
–link 的网络原理
其网络通信原理是在容器中配置 host,即在指定容器的 /etc/hosts 文件中添加容器名和 IP 地址映射。所以通过 --link 建立的网络连接是单向的,若容器 A 与容器 B 建立了一条网络连接,只能从 A 向 B 通信,反之则不可。
目前 --link 设置容器互连的方式已经不推荐使用。更多地选择自定义网络。
自定义网络
我们可以通过 docker network create
命令来创建一个自定义网络。命令说明:
docker network create
创建一个自定义网络
# 创建一个名叫 mynet 的网络,它的网络模式是 桥接(bridge),网段是 192.168.0.0/16,网关是 192.168.0.1
[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 网络列表
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
51604e1eac75 bridge bridge local
9182708c0a34 host host local
2c61a06248d3 mynet bridge local
895dbec7357c none null local
查看自定义的网络信息
[root@localhost ~]# docker network inspect mynet
网络创建好以后,我们就可以把创建的服务放到自己创建的网络当中。
使用自定义网络
现在我们就可以启动容器,并让他们使用自定义网络了。如下,我启动两个Tomcat容器。
[root@localhost ~]# docker run -it --name tomcat-net-01 --net mynet tomcat:8.0.20
[root@localhost ~]# docker run -it --name tomcat-net-01 --net mynet tomcat:8.0.20
此时,再看看我们的自定义网络,会发现网络中多了两个容器信息。
现在我们在 tomcat-net-01 中直接 ping tomcat-net-02
就可以直接连通。
自定义网络的好处
✓ 自定义网络默认支持 ping 容器名
✓ 可以使不同的集群使用不同的网络,保证集群是安全健康的
网络连通
完成自定义网络后,我们如何实现不同网络间的容器网络连接呢?也就是说,在两个不同的网络间实现网络互通,即 docker0 和 mynet自定义网络 建立网络连接。
这时我们可以通过 docker network connect [Options] NetworkName ContainerName
命令打通不同网络之间的容器连接。
# 建立网络连接
[root@localhost ~]# docker network connect mynet tomcat01
# 查看网络信息
[root@localhost ~]# docker network inspect mynet
# 验证网络是否打通了
[root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01
PING centos-net-01 (192.168.0.3): 56 data bytes
64 bytes from 192.168.0.3: icmp_seq=0 ttl=64 time=0.086 ms
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.205 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.242 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.086 ms
# 但是此时 tomcat02 是连不通的,因为 tomcat02 与 mynet 还没有建立网络连接
[root@localhost ~]# docker exec -it tomcat02 ping centos-net-01
ping: unknown host
结论:假设要跨网络操作别人,首先需要使用 docker network connect
来实现网络连通!
Docker Compose 是对 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器。
使用三部曲:
docker-compose up
启动整个应用# 下载 docker-compose,你可以通过修改URL中的版本,可以自定义您的需要的版本
[root@localhost ~]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 修改可执行权限
[root@localhost ~]# chmod +x /usr/local/bin/docker-compose
# 查看版本,安装成功
[root@localhost bin]# docker-compose -version
docker-compose version 1.25.5, build 8a1c60f6
# 默认使用docker-compose.yml构建镜像
[root@localhost ~]# docker-compose build
[root@localhost ~]# docker-compose build --no-cache
# 指定不同yml文件模板用于构建镜像
[root@localhost ~]# docker-compose build -f docker-compose-1.yml
# 列出Compose文件构建的镜像
[root@localhost ~]# docker-compose images
# 启动所有编排容器服务,该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
[root@localhost ~]# docker-compose up -d
# 查看正在运行中的容器
[root@localhost ~]# docker-compose ps
# 查看所有编排容器,包括已停止的容器
[root@localhost ~]# docker-compose ps -a
# 停止 up 命令所启动的容器,并移除网络
[root@localhost ~]# docker-compose down
# 进入指定容器执行命令
[root@localhost ~]# docker-compose exec nginx bash
[root@localhost ~]# docker-compose exec web python manage.py migrate --noinput
# 查看web容器的实时日志
[root@localhost ~]# docker-compose logs -f web
# 启动已经存在的服务容器
[root@localhost ~]# docker-compose start
# 停止已经处于运行状态的容器,但不删除它,可以再次重启
[root@localhost ~]# docker-compose stop
# 重新启动停止服务的容器
[root@localhost ~]# docker-compose restart web
# 暂停web容器
[root@localhost ~]# docker-compose pause web
# 恢复web容器
[root@localhost ~]# docker-compose unpause web
# 删除web容器,删除前必需停止stop web容器服务
[root@localhost ~]# docker-compose rm web
# 查看各个服务容器内运行的进程
[root@localhost ~]# docker-compose top
# 版本号
version: "3"
# 服务
services:
# 服务名称
redis:
# 镜像名: 仓库/标签:版本
image: redis:alpine
# 暴露端口信息
ports:
- "6379"
# 添加环境变量.可以使用数组或字典两种形式
# 任何布尔值:true, false, yes, no 需要用引号括起来,以确保它们不被YAML解析器转换为True或False
environment:
db:
image: postgres:9.4
# 定义全局挂载卷
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
# 创建一个新的项目目录
[root@localhost home]# mkdir wp_compose
# 进入到项目目录
[root@localhost home]# cd wp_compose
# 创建 docker-compose.yml 文件,编排你的服务,主要内容包括WordPress博客和一个单独的MySQL实例卷挂载数据持久化
[root@localhost wp_compose]# vim docker-compose.yml
version: "3.3"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
# 启动博客项目
[root@localhost home]# docker-compose up -d
# 预览效果
http://your_ip:8000/
欢迎关注我的个人公众号:小瓦匠学编程,优质好文不错过!扫描二维码或微信搜索 “小瓦匠学编程” 即可关注。
(本文完)