基础篇
Docker概述
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。Docker 容器不需要额外的虚拟化,因为它们在内核级别运行,这使得它们比传统的虚拟机更轻量级、更快速、更便携。Docker 容器可以在任何地方运行,包括开发人员的笔记本电脑、数据中心的物理服务器、虚拟机、公有云、私有云、Kubernetes集群等。
Docker 不需要像传统虚拟机一样运行完整的操作系统,而是共享宿主机的操作系统内核,从而实现更高效的资源利用和更快的启动时间。 可以更方便地进行部署和管理,因为它们可以被打包成镜像并在不同的环境中运行,而无需担心环境差异带来的问题。
Docker 比虚拟机快的原因:
- 更少的抽象层 。由于 docker 不需要 Hypervisor (虚拟机)实现硬件资源虚拟化,运行在 docker 容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上 docker 将会在效率上有明显优势。
- 利用的是宿主机的内核,而不需要加载操作系统 OS 内核 。 当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程。当新建一个虚拟机时,虚拟机软件需要加载 OS,返回新建过程是分钟级别的。而 docker 由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个 docker 容器只需要几秒钟。
Docker是一个(C/S)架构的程序,Client通过接口与Server进程通信实现容器的构建,运行和发布。有以下几个核心组件:
- 客户端:Docker命令行工具,用户是用 Docker Client 与 Docker daemon 进行通信并返回结果给用户
- 宿主机 docker_host:安装了Docker程序,并运行了Docker daemon(守护进程) 的主机
- 镜像 images :将软件环境打包好的模板,用来创建容器的,一个镜像可以创建多个容器
- 容器 containers:Docker的运行组件,启动一个镜像就是一个容器,容器与容器之间相互隔离,并且互不影响
- 仓库服务注册 registry :可以有多个仓库,每个仓库可以看成是一个用户,一个用户的仓库放了多个镜像。仓库分为了公开仓库(Public Repository)和私有仓库(Private Repository),最大的公开仓库是官方的Docker Hub,国内也有如阿里云。用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
Docker的安装
Install Docker Engine on CentOS | Docker Documentation
CentOS 7 下安装:
确保是CentOS 是 7 及以上,可以通过 cat /etc/redhat-release
查看
- 卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2. yum安装gcc相关
yum -y install gcc
yum -y install gcc-c++
3. 安装软件包并且设置stable镜像仓库
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4. 更新yum软件包索引
yum makecache fast
5. 安装 docker ce
yum -y install docker-ce docker-ce-cli containerd.io
6. 启动和测试 docker
systemctl start docker
docker version
docker run hello-world
docker run 的运行流程图:
配置镜像加速器
卸载相关命令
systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
Docker的常用命令
启动类相关命令
启动 docker:systemctl start docker
停止 docker:systemctl stop docker
重启 docker:systemctl restart docker
查看 docker 状态:systemctl status docker
开机启动:systemctl enable docker
查看 docker 信息:docker info
总体帮助文档:docker --help
命令帮助文档:docker 命令 --help
镜像命令
docker images
# 列出本地主机上的镜像
docker images
# 列出本地所有的镜像(含历史映像层)
docker images -a
# 只显示镜像ID
docker images -q
# 参数说明
# REPOSITORY:表示镜像的仓库源
# TAG:镜像的标签版本号
# IMAGE ID:镜像IDCREATED:镜像创建时间
# SIZE:镜像大小
# 同一仓库源可以有多个TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
docker search
# 查找镜像
docker search centos
# 只列出N个镜像,默认25个
docker search --limit 5 redis
docker pull
# 下载镜像,冒号后面是版本号可选,默认是latest
docker pull centos:7
docker system df
# 查看镜像/容器/数据卷所占的空间
docker system df
docker rmi
# 删除镜像
docker rmi centos
# 删除单个
docker rmi -f 镜像ID
# 删除多个
docker rmi -f 镜像名1:TAG 镜像名2:TAG
# 删除全部
docker rmi -f $(docker images -qa)
容器命令
有镜像才能创建容器
docker run
# 启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# --name="容器新名字" :为容器指定一个名称;
# -d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);
# -i:以交互模式运行容器,通常与 -t 同时使用;
# -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;也即启动交互式容器(前台有伪终端,等待交互);
# -P: 随机端口映射,大写P
# -p: 指定端口映射,小写p
docker run -it centos:7 /bin/bash
# 参数说明:-i: 交互式操作。-t: 终端。centos : centos 镜像。/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。要退出终端,直接输入 exit:
docker run -d --name=mredis -p 80:6379 redis
docker ps
# 列出当前所有正在运行的容器
docker ps [OPTIONS]
# -a :列出当前所有正在运行的容器+历史上运行过的
# -l :显示最近创建的容器。
# -n:显示最近n个创建的容器。
# -q :静默模式,只显示容器编号。
退出容器
# run进去容器,exit退出,容器停止
exit
# run进去容器,ctrl+p+q退出,容器不停止
ctrl+p+q
停止/重启容器
# 启动已停止运行的容器
docker start 容器ID或者容器名
# 重启容器
docker restart 容器ID或者容器名
# 停止容器
docker stop 容器ID或者容器名
# 强制停止容器
docker kill 容器ID或容器名
# 删除已停止的容器
docker rm 容器ID
# 一次性删除多个容器实例
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
容器信息查询
# 查看容器日志
docker logs 容器ID
# 查看容器内运行的进程
docker top 容器ID
# 查看容器内部细节
docker inspect 容器ID
进入正在运行的容器
# exec 是在容器中打开新的终端,并且可以启动新的进程 用exit退出,不会导致容器的停止(推荐使用)
docker exec -it 容器ID bashShell
# attach 直接进入容器启动命令的终端,不会启动新的进程 用exit退出,会导致容器的停止
docker attach 容器ID
# 进入 redis 容器
docker exec -it 容器ID /bin/bash
docker exec -it 容器ID redis-cli
容器内拷贝文件到主机
docker cp 容器ID:容器内路径 目的主机路径
docker commit
# 提交容器
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
docker 命令总结:
attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像 build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像 commit Create a new image from a container changes # 提交当前容器为新的镜像 cp Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中 create Create a new container # 创建一个新的容器,同 run,但不启动容器 diff Inspect changes on a container's filesystem # 查看 docker 容器变化 events Get real time events from the server # 从 docker 服务获取容器实时事件 exec Run a command in an existing container # 在已存在的容器上运行命令 export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
Docker镜像
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件。所有的应用,直接打包成docker镜像,就可以直接跑起来。
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统称为 UnionFs(联合文件系统)。Docker镜像层都是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的顶部。
Union 文件系统是一种分层、轻量级并且高性能的文件系统,是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
bootfs(boot file system) 主要包含 bootloader 和 kernel, bootloader 主要是引导加载 kernel。Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层是引导文件系统 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs (root file system) ,在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs 就是各种不同的操作系统发行版,比如 Ubuntu,Centos等等。 平时我们安装进虚拟机的 CentOS 都是好几个G,为什么docker这里才200M??对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的 linux 发行版, bootfs 基本是一致的, rootfs 会有差别, 因此不同的发行版可以公用 bootfs。
下载镜像时,观察下载的日志输出,可以看到是一层一层的在下载。
Docker数据卷
卷就是目录或文件,存在于一个或多个容器中,由 Docker 挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性,将docker容器内的数据保存进宿主机的磁盘中。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接实时生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
当启动容器时可以通过 -v 来挂载数据卷
# 宿主vs容器之间映射添加容器卷
docker run -it --name=mr -v /宿主机绝对路径目录:/容器内目录 redis /bin/bash
# 读写规则映射添加说明:默认为rw支持读写,ro 容器实例内部被限制,只能读取不能写
docker run -it --name=mr -v /宿主机绝对路径目录:/容器内目录:rw redis /bin/bash
docker run -it --name=mr -v /宿主机绝对路径目录:/容器内目录:ro redis /bin/bash
# 卷的继承和共享
docker run -it --name=mr1 -v /宿主机绝对路径目录:/容器内目录 redis
docker run -it --name=mr2 --volumes-from=mr1 redis
需要注意的是,如果挂载主机目录Docker访问出现cannot open directory .: Permission denied错误,只需在挂载目录后多加一个--privileged=true
参数即可。
DockerFile
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。通过 docker build 命令可以构建镜像。
dockerFile 脚本常用的命令,命令必须要大写
FROM:指定基础镜像,必须为第一个命令
格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
示例:
FROM mysql:5.6
注:
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
MAINTAINER:维护者信息
格式:
MAINTAINER <name>
示例:
MAINTAINER HCM
MAINTAINER HCM@163.com
MAINTAINER HCM <HCM@163.com>
RUN:构建镜像时执行的命令
RUN 用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
RUN <command>
exec执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
注:
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。
如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget。
COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
格式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/
CMD:构建容器后调用,也就是在容器启动时才进行调用。但是一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD。
CMD主要用于container时启动指定的服务,当docker run command的命令匹配到CMD command时,会替换CMD执行的命令
格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
示例:
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
注:
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去"application",只使用参数。
格式:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
ENTRYPOINT command param1 param2 (shell内部命令)
示例:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
注:
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,
而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。
Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
LABEL:用于为镜像添加元数据
格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。
推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
ENV:设置环境变量
格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
EXPOSE:指定于外界交互的端口
格式:
EXPOSE <port> [<port>...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
注:
EXPOSE并不会让容器的端口访问到主机。
要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
VOLUME:用于指定持久化目录
格式:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2" 注: 一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能: 1、卷可以容器间共享和重用 2、容器并不一定要和其它容器共享卷 3、修改卷后会立即生效 4、对卷的修改不会对镜像产生影响 5、卷会一直存在,直到没有任何容器在使用它
WORKDIR:工作目录,类似于cd命令
格式:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。
在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
USER:指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
格式:
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group
示例:
USER www
注:
使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
ARG:用于指定传递给构建运行时的变量
格式:
ARG <name>[=<default value>]
示例:
ARG site
ARG build_user=www
ONBUILD:用于设置镜像触发器
格式:
ONBUILD [INSTRUCTION]
示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发
构建自己的 tomcat
通过已下命令提前准备好资源
vim readme.txt
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-linux-x64.tar.gz
wget --no-check-certificate --no-cookies https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.75/bin/apache-tomcat-9.0.75.tar.gz
vim mdockerfile
FROM centos
MAINTAINER yibo<718649016@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr/local/
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.22/logs/catalina.out
# 构建镜像 -f:指定 dockerfile 文件 -t:指定镜像名
docker build -f mdockerfile -t mtomcat .
# 启动镜像
docker run -d -p 8080:8080 mtomcat
Docker网络
【扩展】VMware 软件三种网络模式
对于许多接触 Linux 操作系统的朋友而言,起初都是通过虚拟机软件进行层层深入的学习。在使用自己的电脑时通常情况下是使用 VMware 来创建虚拟机。在创建过程中可以对网络适配器进行设置,在网络连接方式上提供了5种模式,对于前三种:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)做一个学习:
桥接模式
- 概念:桥接模式就是一种将主机(好比是你的笔记本上的)的网卡与虚拟机的网卡利用虚拟网桥进行通信。
- 原理理解:对这种模式的理解可以认为是将物理机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,当然物理机也一样需要连接到这个交换机,也就是说桥接模式下的所有网卡都是交换模式,相互可以访问而且互不干扰。
- 典型特征:虚拟机的IP地址需要与主机在同一网段,如果需要联网则网关与DNS需要与主机网卡一致。
NAT模式
- 概念:网络地址转换模式,借助的是虚拟的 NAT 设备以及虚拟的 DHCP 服务器,从而使得虚拟机可以联网
- 原理理解:在 NAT 模式中,主机网卡直接与虚拟 NAT 设备相连,然后虚拟NAT设备与虚拟DHCP服务器一起连接在虚拟交换机VMnet8上,这样就实现了虚拟机联网。VMware Network Adapter VMnet8 虚拟网卡主要是为了实现主机与虚拟机之间的通信。
Host-Only 模式
- 概念:主机模式,没有NAT设备的网络模式
- 原理理解:使用的是VMnet1虚拟网卡与虚拟交换机连接,从而与虚拟机通信,而这种模式就实现了虚拟机与外网的隔离,即独立的一台服务器,只与主机互相通信
Docker网络实现原理
Docker 使用 linux 桥接,在宿主机虚拟一个docker 容器网桥(docker0) ,docker 启动一个容器时会根据docker 网桥的网段分配给容器一个IP地址,称为Container-IP,Docker0 是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
通过 docker0 实现了容器间的互联和通信,端口的映射,当容器IP变动时候可以通过服务名直接网络通信。
docker 网络相关的指令如下:
# 查看网络列表
docker network ls
# 不指定网络驱动时默认创建的bridge网络:
docker network create test-create
# 创建网络时,使用参数`-d`指定驱动类型为overlay
docker network create -d overlay my-multihost-network
# 删除指定的网络,如果网络中有容器连接需要加 -f 参数强制删除,建议不要这样执行,网络中若没有任何容器连接直接执行删除即可.
docker network rm test-create
# 查看一个网络的详情
docker network inspect test-create
# 删除所有未使用的网络
docker network prune
# 将一个容器加入到一个网络中
docker network connect 网络名称 容器ID
# 从网络中断开一个容器的链接
docker network disconnect 网络名称 容器 ID
Docker 的网络模式(4+1)
- Host: 容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口
- Container: 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围
- None: 该模式关闭了容器的网络功能。
- Bridge: 默认为该模式,此模式会为每一个容器分配,设置IP等,并将容器连接到一个docker0 的虚拟网桥,通过docker 0 网桥以及iptables nat 表配置与宿主机通信。
- 自定义网络
在安装 Docker 时,它会自动创建三个网络:bridge(默认),none,host。使用 docker run
创建 Docker 容器时,可以用 --net
或 --network
选项指定容器的网络模式
- host模式:使用 --net=host 指定。
- none模式:使用 --net=none 指定。
- container模式:使用 --net=container:NAME/ID 指定。
- bridge模式:使用 --net=bridge 指定,默认设置,可省略。
bridge模式
docker run 的时候,没有指定 network 的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机 ifconfig ,就可以看到 docker0 和自己 create 的network 。eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址
网桥 docker0 创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。通过这种方式,将宿主机上的所有容器都连接到这个内部网络上,不同的容器在同一个网络下,会从这个网关下各自拿到分配的ip,此时不同容器的网络是互通的。
host模式
容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口
在docker启动时指定--network=host或-net=host,如果还指定了-p映射端口,那这个时候就会出现警告
none 模式
在none模式下,并不为 Docker 容器进行任何网络配置,即禁用网络功能。 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo(就是127.0.0.1表示本地回环) 需要我们自己为 Docker 容器添加网卡、配置IP等。
container 模式
新建的容器和已经存在的一个容器共享一个网络 ip 配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
这种模式节约了一定数量的网络资源,但它并没有改变容器与外界通信的方式。在一些特殊的场景中非常有用,例如,kubernetes的pod,kubernetes为pod创建一个基础设施容器,同一pod下的其他容器都以其他容器模式共享这个基础设施容器的网络命名空间,相互之间以localhost访问,构成一个统一的整体。
自定义网络模式
通过 docker network create
可以创建自定义的网络模式,在自定义网络模式下,docker 提供了五种自定义网络驱动:
- bridge:默认的 bridge 网络模式,将 Docker 容器连接到docker。默认创建的 docker0 网桥上面,如果未指定 --network 选项,创建的容器将默认指向 docker0,该驱动即对应docker的bridge网络模式,通过NAT地址转换使容器和外界进行通信。
- overlay:驱动采用IETE标准的VXLAN方式,主要用于创建容器的跨主机网络,对应docker的user-defined网络模式
- macvlan:允许宿主机将一个 MAC 地址分配给 Docker 容器,使它在网络中显示为一个物理设备
- host:连接单个容器和宿主机之间的通信,使得容器能够直接使用宿主机的网络
- none:禁用容器的所有网络,通常和自定义网络驱动一起使用,集群模式不可用
自定义桥接的网络模式下通过容器 name ping 通(docker0 是无法 ping 通)
实践篇
常用镜像安装和使用
镜像的安装分为以下几步:搜索镜像--->拉取镜像--->查看镜像--->启动镜像--->停止容器--->移除容器,注意端口映射
安装并使用 tomcat
# docker hub上面查找tomcat镜像
docker search tomcat
# 从docker hub上拉取tomcat镜像到本地
docker pull tomcat
# docker images查看是否有拉取到的tomcat
docker images tomcat
# 使用tomcat镜像创建容器实例(也叫运行镜像)
docker run -it -p 8080:8080 tomcat
# 如果访问无首页可能是端口没开放或者 webapps 文件夹下无内容
rm -r webapps
mv webapps.dist webapps
安装mysql
docker search mysql
docker pull mysql:5.7
docker run
-p 3306:3306 --name mysql # 配置端口映射
-v /mydata/mysql/log:/var/log/mysql # 将容器中的日志文件夹挂载到主机对应的/var/log/mysql文件夹中
-v /mydata/mysql/data:/var/lib/mysql # 将容器中的数据文件夹挂载到主机对应的/var/lib/mysql文件夹中
-v /mydata/mysql/conf:/etc/mysql # 将容器的配置文件夹挂载到主机对应的/etc/mysql文件夹中
-e MYSQL_ROOT_PASSWORD=root # 设置初始化root用户的密码
-d mysql:5.7 # -d:以后台方式运行实例
安装单机版 redis
docker pull redis
mkdir -p /app/redis
cd /app/redis
vim redis.conf # 配置部分省略,或者直接copy一份默认的配置文件
docker run
-p 6379:6379 --name myr3 --privileged=true
-v /app/redis/redis.conf:/etc/redis/redis.conf # 将容器中的配置文件挂载到主机对应的 /app/redis/ 文件夹中
-v /app/redis/data:/data # 将容器中 rdb 文件挂载到主机对应的 /app/redis/ 文件夹中
-d redis:6.0.8 redis-server /etc/redis/redis.conf # -d:以后台方式运行,通过 redis-server 按照自定义的配置启动
配置 redis 集群
集群配置如下:
- docker端口号→宿主机对外暴露的端口:7000→7000,7001→7001,7002→7002,7003→7003,7004→7004,7005→7005
- 挂载目录:data(数据) → /cluster/data/ conf(配置文件)→ /cluster/redis.conf
- 集群模式:三主三从
- 节点容器名称:redis-7000,redis-7001,redis-7002,redis-7003,redis-7004,redis-7005
创建好挂载目录和配置文件
mkdir cluster
cd cluster
mkdir data
vim redis70.conf
添加配置信息,其他5份配置文件直接 copy 修改端口号相关的配置项
bind 0.0.0.0 # 则所有IP可连接
daemonize yes # 守护进程(后台)的方式运行
protected-mode no
port 7000
dbfilename dump7000.rdb
appendonly yes # aof模式开启
appendfilename "appendonly6381.aof"
requirepass 111111
masterauth 111111
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
[root@localhost cluster]# cp redis70.conf redis71.conf
[root@localhost cluster]# cp redis70.conf redis72.conf
[root@localhost cluster]# cp redis70.conf redis73.conf
[root@localhost cluster]# cp redis70.conf redis74.conf
[root@localhost cluster]# cp redis70.conf redis75.conf
接下来就可以创建每个节点的docker容器
# 创建7000节点容器
docker run \
--name=redis7000 --privileged=true --net host \
-v /cluster/redis70.conf:/etc/redis/redis.conf \
-v /cluster/data:/data \
-d redis redis-server /etc/redis/redis.conf
# 如果无法启动容器后状态仍 exited,可以分布完成
docker run \
--name=redis7000 --privileged=true --net host \
-v /cluster/redis70.conf:/etc/redis/redis.conf \
-v /cluster/data:/data \
-it redis /bin/bash
redis-server /etc/redis/redis.conf
此时我们已经创建好了所有节点,但各个节点还是相互独立的,我们需要将他们整合成集群,执行以下命令建立集群
redis-cli --cluster create --cluster-replicas 1 \
192.168.186.141:7000 192.168.186.141:7001 192.168.186.141:7002 \
192.168.186.141:7003 192.168.186.141:7004 192.168.186.141:7005
镜像发布到阿里云
- 创建阿里云仓库镜像
进入阿里云开发者平台,选择控制台,进入容器镜像服务 ---> 选择个人实例 --->创建命名空间--->创建镜像仓库,选择本地仓库--->获取脚本
- 将镜像推送到阿里云