镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像,在Docker中镜像名称一般分两部分组成:[repository]:[tag]
,- 在没有指定tag时,默认是latest,代表最新版本的镜像。
容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器进程做隔离,对外不可见。
一切应用最终都是代码组成,都是硬盘中的一个个的字节形成的文件。只有运行时,才会加载到内存,形成进程。
镜像
,就是把一个应用在硬盘上的文件、及其运行环境、部分系统函数库文件一起打包形成的文件包。这个文件包是只读的。
容器
,就是将这些文件中编写的程序、函数加载到内存中允许,形成进程,只不过要隔离起来。因此一个镜像可以启动多次,形成多个容器进程。
开源应用程序非常多,打包这些应用往往是重复的劳动。为了避免这些重复劳动,人们就会将自己打包的应用镜像,例如Redis、MySQL镜像放到网络上,共享使用,就像GitHub
的代码共享一样点击跳转DockerHub。
DockerHub:DockerHub是一个官方的Docker镜像的托管平台。这样的平台称为Docker Registry。
国内也有类似于DockerHub 的公开服务,比如 网易云镜像服务、阿里云镜像库等
我们一方面可以将自己的镜像共享到DockerHub,另一方面也可以从DockerHub拉取镜像 官网地址
我们要使用Docker来操作镜像、容器,就必须要安装Docker。
Docker是一个CS架构的程序,由两部分组成:
服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等
客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。
容器在系统环境中有三个状态,分别是运行
,暂停
,停止
。
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷,·一句话有点类似我们Redis里面的rdb和aof文件,将docker容器内的数据保存进宿主机的磁盘中。
特点
:
systemctl start docker
systemctl stop docker
systemctl status docker
systemctl restart docker
systemctl enable docker
systemctl disable docker
docker version
systemctl daemon-reload
docker [命令] --help
docker images [OPTIONS]
同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
相关参数OPTIONS说明
docker search [OPTIONS] 镜像名
相关参数OPTIONS说明
docker pull 镜像名字[:TAG]
没有指定[:TAG]
的话,默认就是使用latest
,代表最新版本的镜像。Using default tag: latest:使用默认的标签latest,有想要查找的镜像可以到DockerHub中去搜索。
docker system df
删除一个镜像
docker rmi [OPTIONS] [仓库名]/[id]
删除多个镜像
docker rmi [OPTIONS] 镜像名1:TAG 镜像名2:TAG ......
删除全部镜像
docker rmi -f $(docker images -qa)
相关参数OPTIONS说明
将本地的镜像保存压缩为一个 .tar 的压缩包,可以保存多个镜像到这个压缩文件中
保存在当前所在目录
docker save -o [保存的目标文件名称] 镜像名字[:TAG]/镜像ID
docker save 镜像名字[:TAG] -o [保存的目标文件的路径]
将指定的镜像压缩包加载为镜像
docker load -i [镜像压缩包路径]
相关参数OPTIONS说明
docker tag [旧镜像名]:[版本] [新镜像名]:[版本]
根据镜像创建出一个容器,并运行容器(容器处于运行状态),如果本地没有这个容器就会到远程仓库下载
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
案例1:启动一个nginx容器,并后台运行。
docker run --name mynginx -p 80:80 -d nginx
案例2:启动一个Centos交互式容器 用bash也可以
注意:其中这种类型的容器是不能使用 -d 后台运行的会自动退出,这种是前台交互式启动
docker run -it centos /bin/bash
相关参数OPTIONS说明
前台交互式启动
-d 的方式称为 后台守护式启动
第一种方法
bash是linux终端的交互命令,也可以换成其他命令
docker exec -it [容器名] bash
第二种方法
docker attach [容器ID]
两种方法的区别
run进去容器
,从容器的交互模式下退出,有两种办法。
注意:
这种退出方法,容器会停止运行
第一种: 输入 exit 加 回车
注意:
这种退出方法容器不会停止运行
第二种: ctrl+p+q退出
退出容器的方式和效果会根据进入容器的方式产生差别,建议参考上一章。
默认不能删除在运行状态中的容器,可以使用 -f 强制删除
docker rm [OPTIONS] [容器名]
删除所有的容器 慎用
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
相关参数OPTIONS说明
重启指定的容器
docker restart [容器ID]/[容器名]
查看指定容器的运行日志
docker logs [OPTIONS] [容器名]
相关参数OPTIONS说明
默认只能查看运行中的容器
docker ps [OPTIONS]
相关参数OPTIONS说明
让一个运行状态的容器变成暂停状态
docker pause [容器ID]/[容器名]
让一个暂停状态的容器,重新变成运行状态
docker unpause [容器ID]/[容器名]
让一个运行状态的容器变成停止状态
docker stop [容器ID]/[容器名]
启动一个停止状态的容器,相当于新创建了一个进程
docker start [容器ID]/[容器名]
docker inspect [容器ID]
从容器内拷贝一文件到宿主主机
docker cp 容器ID:容器内路径 目的主机路径
将宿主机中的文件拷贝到容器内部 用容器id或者容器名都行
docker cp 宿主机文件路径 容器ID:docker容器内路径
export 导出容器的内容留作为一个tar归档文件,默认导出到当前目录,相当于备份了整个容器。
docker export 容器ID > 文件名.tar
import 从tar包中的内容创建一个新的文件系统再导入为镜像
docker import 文件名.tar 镜像用户/镜像名:镜像版本号
值得注意的是启动这种镜像后面 必须加 bash 且必须用 -it
注意
:导出的容器并不会同步数据卷中的配置,要想同步数据卷中的配置只有修改容器内内容。
Docker镜像层都是只读的,容器层是可写的,docker commit提交容器副本使之成为一个新的镜像
。
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
Docker中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似Java继承于一个Base基础类,自己再按需扩展,标签名也就是版本。
OPTIONS说明
注意
:导出的容器并不会同步数据卷中的配置,要想同步数据卷中的配置只有修改容器内内容。
使用以下命令可以查看当前系统所有容器的资源占用信息
docker stats
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法
:在挂载目录后多加一个–privileged=true参数即可
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限
如果当前宿主机没有这个绝对目录那么会帮我们自动创建出来,可以使用多个 -v 绑定多个容器卷。
即使容器是停止状态,修改宿主机容器卷,容器里面的容器卷里面的内容也会被同步,因为使用的是默认的规则可读也可写。
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
使用inspect命令可以查看容器的详细信息,在详细信息中就可以找到绑定的容器卷。
docker inspect [容器ID]
默认没有指定读写规则的话就是可读也可写,相当于下面这条命令。
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
只读设置
:容器实例内部被限制,只能读取不能写
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
如果强行在容器内的容器卷添加文件等操作则会报出下面的错误,会被限制。
我以一个小案例的方式来进行演示
容器1完成和宿主机的映射
docker run -it --privileged=true -v /mydocker/u:/tmp/u --name u1 ubuntu
容器2继承容器1的卷规则,父类就是我们上面的u1
docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
这样u1和宿主绑定的容器卷,u2也会实时同步,这样就实现了容器之间卷的共享。
即使u1已经停止运行,我们在宿主机上修改绑定其的容器卷,u2还是可以时实同步宿主机的数据。
安装启动一个容器都是这么几个步骤: 搜索镜像–>·拉取镜像–>查看镜像–>启动镜像–>服务端口映射–>停止容器–>移除容器
第一步我们就是要先查找以下tomcat的镜像,可以在docker hub上面查找tomcat镜像,也可以执行以下命令进行查找,这条命令上面有详细介绍。
docker search tomcat
选择好后直接执行以下命令将镜像拉取到本地,这里我们拉去的是最新版本的。
docker pull tomcat
拉取到本地后可以执行以下命令查看一下是否拉取成功
docker images
然后直接执行命令运行容器就可以了,tomcat默认默认监听的是8080端口
docker run --name tomcat-test -d -p 8080:8080 tomcat
执行以下命令查看是否启动成功
docker ps
然后就可以用主机名:8080访问tomcat了,直接访问会是这个效果,因为新版本对首页的访问发生了一些变化,这种情况是正常的
我们可以用以下命令进入容器
docker exec -it [容器id] bash
如果我们想看到那只猫的首页的话应该是webapps目录
我们进去webapps里面,发现里面啥也没有,所以我们啥也访问不到
我们直接执行命令删除webapps 真正的首页藏在webapps.dist中
rm -r webapps
将webapps.dist 修改名称为 webapps
mv webapps.dist webapps
这样我们再去访问 主机:8080 不出意外那只猫就回来了
如果不想这么麻烦其实可以用免修改版,也是低点的版本,直接执行下面的命令即可
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
注意点: 宿主机的8080端口要对外开放,且没有别的软件在监听
首先我们可以到DockerHub上搜索一下找到想要的版本。
可以看到直接给我们提供了拉取的命令。
我们直接执行以下命令拉取mysql的镜像当前最新版本是8.0.31
docker pull mysql
拉取成功后就可以执行以下命令启动容器了,注意在启动前如果当前系统有服务占用3306端口,会报错向下面这样,需要关闭掉。
MYSQL_ROOT_PASSWORD 指定的是root密码
// 简化版启动 推荐使用下面的
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
挂载数据卷启动
,内容内的数据等信息保存一份在宿主机,这样即使容器挂了数据也保存在宿主机上。
// 挂载数据卷启动
docker run -d -p 3306:3306 --privileged=true -v /mysql_test/mysql/log:/var/log/mysql -v /mysql_test/mysql/data:/var/lib/mysql -v /mysql_test/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql
可以看到直接就启动成功了,然后就可以执行 docker ps 来检查一下
紧接着我们就可以执行命令进入容器内
docker exec -it [容器ID] /bin/bash
然后执行以下命令回车输入密码即可进入mysql
mysql -uroot -p
如果要进行远程连接的话,只要放行宿主机上的3306端口就可以了
注意如果是插入中文数据会有一个报错,是因为docker上默认字符集编码隐患
在mysql服务内执行以下的命令就可以看到默认的字符集,全是拉丁。
SHOW VARIABLES LIKE 'character%';
因为我们挂载了数据卷,我们可以通过修改mysql的配置文件,达到一个修改编码的问题。
// 进入数据卷
cd /mysql_test/mysql/conf
// 新建配置文件
touch my.cnf
将以下面内容添加到 my.cnf 文件
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
docker restart [容器ID]/[容器名]
不出意外的话就可以插入中文数据了
假如我们将mysql容器删除,再使用上面的命令挂载数据卷启动,保留在宿主机数据卷中的数据会重新写入到新的mysql容器中,所以说挂载容器卷很重要
。
关于镜像的搜索这里就不过多讲解了,可以到DockerHub上搜索想要的版本,小编这里直接演示安装最新的版本,执行以下命令拉取镜像。
docker pull redis
这次我们先将容器卷的环境准备好
mkdir -p /redis_test/redis
然后将一个名为redis.conf 的配置文件存放到 /redis_test/redis 目录下redis.conf 最好是官方默认的配置,实在没有也可以复制下面小编的配置 密码是123456 下面配置好的。
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
# bind 127.0.0.1
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
requirepass 123456
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 30
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
如果复制的是官方默认的配置文件
,则需要修改以下几个点
然后执行以下命令直接启动Redis,同时将数据卷挂载好,注意运行前要确保宿主机6379端口没被占用
docker run -p 6379:6379 --name redis --privileged=true -v /redis_test/redis/redis.conf:/etc/redis/redis.conf -v /redis_test/redis/data:/data -d redis redis-server /etc/redis/redis.conf --requirepass 123456
redis-server /etc/redis/redis.conf 是读取配置文件
–requirepass 123456 注意这个一定要设置要不然远程访问不了,
全体注意
:这里小编又踩了个坑启动容器是报错 :WARNING: IPv4 forwarding is disabled. Networking will not work
;这个会导致docker安装MySQL,redis…等软件无法进行链接
解决办法
:
// 修改配置文件
vim /usr/lib/sysctl.d/00-system.conf
// 新增以下内容
net.ipv4.ip_forward=1
// 接着重启网络
systemctl restart network
// 然后删除原来的容器实例,再新启动一个即可
启动后进入容器内部
docker exec -it [容器ID] /bin/bash
进入内部后直接执行下面命令即可进入redis客户端
redis-cli
想要远程访问的话,得放行当前宿主机的6379端口,然后再重启一下防火墙,可以执行以下命令。
// 放行端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
// 重启防火墙
firewall-cmd --reload
关于镜像的查找以及版本的选择小编就不多做介绍了吧,具体可以参考上面的软件安装步骤。
那我们直接就拉取镜像,这里小编拉取的是最新版的nginx镜像,版本是1.23.2
docker pull nginx
拉取完成后可以执行 docker images 看看是否拉取成功
注意
:直接启动nginx会爆出一个下面这样的错误
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc
create failed: unable to start container process: error during container init: error mounting "/docker-work/nginx/nginx.conf" to rootfs at "/etc/nginx/nginx.conf": mount /docker-
work/nginx/nginx.conf:/etc/nginx/nginx.conf (via /proc/self/fd/6), flags: 0x5000: not a
directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if
the specified host path exists and is the expected type.
如果/docker-work/nginx/nginx.conf文件不存在,这里会出现docker报错,因为docker不允许绑定不存在的文件。
而直接新建一个空的/mydata/nginx/conf/nginx.conf虽然docker不会报错,但是nginx却无法在容器中正常启动,通过docker ps -a命令查看,nginx会处于exit或者一直restart状态,因为nginx的运行依赖于nginx.conf这个配置文件中的相关配置。
所以下面的启动方法可能比较奇怪
:
先准备好容器卷目录
// 创建挂载目录
mkdir -p /docker_work/nginx/conf
mkdir -p /docker_work/nginx/log
mkdir -p /docker_work/nginx/html
启动一个不挂载数据卷的容器
docker run --name nginx -p 9001:80 -d nginx
再将容器的一些配置复制到宿主机
# 将容器nginx.conf文件复制到宿主机
docker cp nginx:/etc/nginx/nginx.conf /docker_work/nginx/conf/nginx.conf
# 将容器conf.d文件夹下内容复制到宿主机
docker cp nginx:/etc/nginx/conf.d /docker_work/nginx/conf/conf.d
# 将容器中的html文件夹复制到宿主机
docker cp nginx:/usr/share/nginx/html /docker_work/nginx/
再删除刚刚创建的那个容器
docker rm nginx -f
再执行以下命令启动容器并挂载数据卷
docker run -p 80:80 --privileged=true --name nginx --net host -v /docker_work/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /docker_work/nginx/conf/conf.d:/etc/nginx/conf.d -v /docker_work/nginx/log:/var/log/nginx -v /docker_work/nginx/html:/usr/share/nginx/html -d nginx:latest
可以看到启动成功
启动成功后直接访问 本机地址:80 就可以看到nginx默认的页面了
特殊参数说明
常见的镜像在DockerHub就能找到,但是我们自己写的项目就必须自己构建镜像了。
而Dockerfile就是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
而要自定义镜像,就必须先了解镜像的结构才行。
简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。
构建自定义的镜像时,并不需要一个个文件去拷贝,打包。
我们只需要告诉Docker,我们的镜像的组成,需要哪些BaseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来Docker会帮助我们构建镜像。
而描述上述信息的文件就是Dockerfile
文件。
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
语法
:
语法规则
:
有点类似于套娃的过程,总的来说就是一堆命令依次依赖执行,从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,Dockerfile是软件的原材料、Docker镜像是软件的交付品、Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例。
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
更新详细语法说明,请参考官网文档 点击跳转
演示资料下载 点击下载
cd /tmp
mkdir docker-demo
cd /tmp/docker-demo
2. 将打包就好的jar项目 docker-demo.jar 上传 还有依赖的jdk8
3. 在里面新建一个名为 Dockerfile 的文件 其内容如下
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
docker build -t javaweb:1.0 .
docker images
docker run --name web -p 8090:8090 -d javaweb:1.0
然后我们可以使用以下命令查看运行的容器
docker ps
// 查看防火墙所有开放端口
firewall-cmd --zone=public --list-ports
// 放行8090端口
firewall-cmd --zone=public --add-port=8090/tcp --permanent
// 重启防火墙
firewall-cmd --reload
然后直接访问 http://主机号:8090/hello/count 就可以看打以下内容了,最后就恭喜各位小伙伴完成镜像的自定义了
虽然我们可以基于Ubuntu基础镜像,添加任意自己需要的安装包,构建镜像,但是却比较麻烦。所以大多数情况下,我们都可以在一些安装了部分软件的基础镜像上做改造。
例如,构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。
需求:基于java:8-alpine镜像,将一个Java项目构建为镜像
mkdir /tmp/docker-demo2
cd /tmp/docker-demo2
然后将我们上一个案例用的那个打包好的项目上传到这个目录,这次我们不用上传jdk
还是同样的配方我们新建一个Dockerfile 的文件 其内容如下
FROM java:8-alpine
COPY ./docker-demo.jar /tmp/app.jar
EXPOSE 8090
ENTRYPOINT java -jar /tmp/app.jar
但是这次我们不再是基于ubuntu 进行构建 而是基于java:8-alpine进行构建这个里面已经包含了我们的jdk环境等,相当于比我们上一次案例节省了很多的配置信息
还是老样子我们直接执行以下命令进行打包
docker build -t javaweb:2.0 .
可以看到直接就构建成功了,关于启动的话小编就不多聊了,跟上个案例是一样的
容器网络实质上也是由Docker为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP协议栈、端口套接字、IP路由表、防火墙等等与网络相关的模块。
能实现容器间的互联和通信以及端口映射,容器IP变动时候可以通过服务名直接网络通信而不受到影响。
Docker网络中有三个核心概念:沙盒
(Sandbox)、网络
(Network)、端点
(Endpoint)。
这三者形成Docker网络核心模型,也就是容器网络模型(Container Network Model)
容器网络模型为容器引擎提供了一套标准的网络对接范式,Docker中,实现这套范式的是Docker所封装的libnetwork模块。
Docker官方提供了五种Docker网络驱动,分别是:Bridge Driver
、Host Driver
、Overlay Driver
、MacLan Driver
、None Driver
。Bridge
和 Overlay
在开发中使用频率较高。
网络模式 | 简介 |
---|---|
host(主机模式) | 相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址 |
bridge(桥梁模式) | 相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。 |
overlay(覆盖模式) | Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。 |
container(容器模式) | 在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。 |
none(无网络模式) | 该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)。 |
上文部分内容摘录于这篇文章,这篇文章讲的更加详细,有兴趣的小伙伴可以跳转阅读 点击跳转
列出网络 安装Docker后,Docker会自动创建三个网络。你可以使用以下命令来列出这些网络:
docker network ls
创建网络 创建出来的网络默认是网桥模式
docker network create [网络名]
删除网络 可以使用以下命令删除已有的网络
docker network rm [网络名]
查看网络详细信息 执行以下命令即可
docker network inspect [网络名]
容器添加网络模式,启动容器时可以给容器设置网络模式,使用 --network 指定,如下
docker run -d --network host --name tomcat83 billygoo/tomcat8-jdk8
默认的容器网络模式,假如现在有两个ubuntu的容器,默认是bridge模式,则两个容器各自有独立的ip地址,可以使用以下命令查看容器信息里面有该容器的网络信息。
docker inspect 容器名
分别查看两个容器的网络信息,会发现两个容器的ip地址都不一样,网关是一样的。但是这种模式存在一个隐患,当一个容器宕机或者销毁,新创建的容器可能会占用上一个销毁容器的IP地址,这样可能会造成服务调用错乱的问题。
总结:为每一个容器分配、设置IP等,并将容器连接小一个 docker0 虚拟网桥,默认为该模式。
直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。启动容器后使用docker ps 查看容器状态,即使配置了端口映射也会发现并没有端口映射如下所示。
docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8
并且会发出一个警告:WARNING: Published ports are discarded when using host network mode,原因是docker启动时指定–network=host或-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增,解决办法就是直接无视或者换一种网络模式,也可以不去指定端口映射这样就不会有警告如使用下面的命令。
docker run -d --network host --name tomcat83 billygoo/tomcat8-jdk8
使用下面的命令查看容器的详细信息
docker inspect 容器名
因为跟宿主机使用的是同一套所以是没有网关和地址的
没有设置-p的端口映射了,如何访问上面启动的tomcat容器呢??
上面启动时设置的端口映射是无效的,tomcat默认是监听8080端口,由于容器和宿主机共用一样的IP地址和网关所以这时只要访问 宿主机IP:8080
即可访问启动的Tomcat容器,相当于在宿主机上面安装了一个Tomca。
none模式表示禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)
在none模式下,并不为Docker容器进行任何网络配置。 也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo需要我们自己为Docker容器添加网卡、配置IP等。
比如使用以下命令启动的容器
docker run -d -p 8084:8080 --network none --name tomcat84 billygoo/tomcat8-jdk8
再使用 docker inspect 容器名 命令查看容器详细信息,可以看到是没有网关和IP地址的。
container⽹络模式 新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
列如以下案例:
先启动两个容器
docker run -it --name alpine1 alpine /bin/sh
依赖 alpine1 容器的网络创建一个容器
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh
注意
:在container模式下两台容器是不能用同一个端口的否则将会造成端口冲突
注:Alpine Linux 是一款独立的、非商业的通用 Linux 发行版,专为追求安全性、简单性和资源效率的用户而设计。 可能很多人没听说过这个 Linux 发行版本,但是经常用 Docker 的朋友可能都用过,因为他小,简单,安全而著称,所以作为基础镜像是非常好的一个选择,可谓是麻雀虽小但五脏俱全,镜像非常小巧,不到 6M的大小,所以特别适合容器打包。
首选我们启动两个Tomcat的容器,默认是网桥模式。
docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8
上述成功启动并用docker exec进入各自容器实例内部,使用以下命令查看各自容器的ip地址
ip addr
在任意一台容器使用ping命令ping另一台容器,是可以ping通的,但是上文也提到过网桥模式容器的ip是存在变动隐患的,所以我们最好是用服务名调用如下。
ping tomcat82
但是这样ping会爆出一个ping:tomcat82:Name or service not known
的错误名字或域名不存在
这样的情况我们就可以使用自定义网络来解决这个问题
我们使用以下命令新建一个自定义网络,自定义网络默认使用的是桥接网络bridge
docker network create yunchuang
再在新建的网络的基础上创建两个容器
docker run -d -p 8081:8080 --network yunchuang --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network yunchuang --name tomcat82 billygoo/tomcat8-jdk8
再进入各自容器的内部,然后我们使用服务名进行ping,发现是可以ping通的。
ping tomcat82
最后总结:
Docker-Compose是Docker官方的开源项目, 负责实现对Docker容器集群的快速编排,基于YAML 格式的配置文件Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。
Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。格式如下:
version: "3.8" // 语法版本
services:
mysql: // 服务名
image: mysql:5.7.25 // 镜像名
environment:
MYSQL_ROOT_PASSWORD: 123 // 环境变量
volumes: // 数据卷配置
- "/tmp/mysql/data:/var/lib/mysql"
- "/tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf"
web: // 服务名
build: . // 构建 从当前目录构建镜像 构建完会帮我们部署
ports: // 端口映射
- "8090:8090"
上面的Compose文件就描述一个项目,其中包含两个容器:
mysql:5.7.25
镜像构建的容器,并且挂载了两个目录docker build
临时构建的镜像容器,映射端口时8090DockerCompose的详细语法参考官网:点击跳转
其实DockerCompose文件可以看做是将多个docker run命令写到一个文件,只是语法稍有差异。
Linux下需要通过命令下载:
// 安装
curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
如果下载速度较慢,或者下载失败,可以使用小编准备的docker-compose文件上传到/usr/local/bin/
点击下载。
然后执行以下命令修改一下文件权限
// 修改权限
chmod +x /usr/local/bin/docker-compose
修改完权限后最好再配置一下Base自动补全命令,执行以下命令即可。
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
如果这里出现错误,需要修改自己的hosts文件,执行下面的命令即可。
echo "本机ip地址 raw.githubusercontent.com" >> /etc/hosts
查看安装版本
docker-compose -v
DcokerCompose总结起来说就是 一文件,两要素,三步骤。
一文件
:docker-compose.yml
两要素
:
三步骤
:
查看帮助
docker-compose -h
启动所有docker-compose服务
docker-compose up
启动所有docker-compose服务并后台运行
docker-compose up -d
停止并删除容器、网络、卷、镜像。
docker-compose down
展示当前docker-compose编排过的运行的所有容器
docker-compose ps
展示当前docker-compose编排过的容器进程
docker-compose top
查看容器输出日志
docker-compose logs yml里面的服务id
检查配置
docker-compose config
检查配置,有问题才有输出
docker-compose config -q
重启服务
docker-compose restart
启动服务
docker-compose start
停止服务
docker-compose stop
虚悬镜像
(dangling image),一般是构建镜像或者删除镜像的时候发生错误产生,导致仓库和标签都是
$ docker images -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> e537b729ad07 7 days ago 500MB
<none> <none> 8e2b040f5783 7 days ago 500MB
可以使用以下命令查看当前系统环境上的所有虚悬镜像
docker images -f dangling=true
删除系统上的虚悬镜像可以使用以下命令,出现警告则输入y回车。
docker image prune
Portainer 是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。
官网地址:点击跳转 | Docker安装地址:点击跳转
可以使用以下命令进行安装:
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
启动完后可以执行 docker ps 命令查看是否启动成功
远程登陆一定记得要开放本机的9000端口
firewall-cmd --zone=public --add-port=9000/tcp --permanent // 放行防火墙8080端口(–permanent永久生效,没有此参数重启后失效)
firewall-cmd --reload // 重启防火墙
第一次登录需创建admin,访问地址: 本机地址:9000 会出行以下的界面
用户名,直接用默认admin 密码一定要八位及以上长度否则不符合规定。
登录后选择本地的Docker
就可以看到监控的Docker服务了
点击进去就可以看到本机Docker上的详细信息
Docker重量级Docker监控平台,容器监控3剑客,CAdvisor监控收集+InfluxDB存储数据+Granfana展示图表。
compose容器编排,一套带走:
新建目录进入创建docker-compose.yml 文件
version: '3.1'
volumes:
grafana_data: {}
services:
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor
ports:
- "8083:8083"
- "8086:8086"
volumes:
- ./data/influxdb:/data
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxsrv:8086
restart: always
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
grafana:
user: "104"
image: grafana/grafana
user: "104"
restart: always
links:
- influxdb:influxsrv
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root
使用以下命令启动
docker-compose up
查看三个容器是否都启动成功,然后要保证当前主机的相关端口被开放
浏览cAdvisor收集服务,http://ip:8080/
influxdb存储服务,http://ip:8083/
grafana展现服务,http://ip:3000 默认帐户密码(admin/admin