一、简介 1.Docker是什么? Docker是一种容器技术 ,就像虚拟机,在自己的电脑中模拟出一台或多台子电脑,“子电脑”和“子电脑”之间,是相互隔离的,互不影响。
容器技术,也是虚拟化技术,属于轻量级的虚拟化,因为虚拟机的占用空间更大,一般都需要几个G,启动也慢,而容器技术恰好没有这些缺点。它不需要虚拟出整个操作系统,因为容器内的应用直接运行在宿主机的内核中,所以它启动时间很快,几秒钟就能完成。
2.Docker可以做什么? Docker可以让开发者构建应用程序时,将它与其依赖环境一起打包到一个容器 中,然后很容易地发布和应用到任意平台中。
可移植性:本地开发的项目想要放在服务器上,需要在服务器上再安装一次项目所依赖的环境,Docker将一整套环境封装成镜像 ,无需重复配置环境,解决运行环境不一致所导致的问题。这样就不会产生“本地运行没问题,可一到服务器上就不行了”的情况。
隔离:不同的项目所依赖的环境不一样,如果把他们依赖的软件都安装在一个服务器上,不仅安装时间长,而且可能会有冲突。Docker容器使应用程序不仅彼此隔离,而且与底层系统隔离。
文档教程:https://docs.docker.com/
中文文档:https://vuepress.mirror.docker-practice.com/
仓库地址:https://hub.docker.com/
3.Docker的核心 Docker有3大核心:镜像、容器、仓库
Docker运行一个程序的过程: 去仓库 把镜像 拉到本地,然后用一条命令把镜像运行起来,变成容器 。
镜像(Images) 镜像是一个特殊的文件系统。它除了提供容器 运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
类似于Linux镜像文件(镜像 ),可以使用同一个镜像文件创建多个Linux系统(容器 )。
比如有一个Tomcat镜像 ,镜像是不能启动的,要使用run命令变成容器 ,服务/项目运行就是在容器 中,当然一个镜像可以创建多个容器。
graph LR;
Tomcat镜像--run-->Tomcat01容器
Tomcat镜像--run-->Tomcat02容器
Tomcat镜像--run-->Tomcat03容器
容器(Containers) 容器是运行程序的地方,里面运行着我们指定的应用,通过镜像来创建的。
镜像=类,容器=实例
仓库(Repository) 存放镜像的地方,和Git类似。
负责对Docker镜像进行管理的,最常用的Registry公开服务,是官方的Docker Hub,这也是默认的 Registry。阿里云等也都有自己的容器服务器,毕竟Docker是在国外的
二、安装Docker 1.环境查看 不同的操作系统安装方式也不同,这里为ubuntu https://www.runoob.com/docker/ubuntu-docker-install.html
# 查看系统架构 root:~# uname -a Linux iZbp1aq6c9kbbexg9cxsqiZ 4.4.0-93-generic #116-Ubuntu SMP Fri Aug 11 21:17:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux# 查看系统信息 root:~# lsb_release -a LSB Version: core-9.20160110ubuntu0.2-amd64:core-9.20160110ubuntu0.2-noarch:security-9.20160110ubuntu0.2-amd64:security-9.20160110ubuntu0.2-noarch Distributor ID: Ubuntu Description: Ubuntu 16.04.3 LTS Release: 16.04 Codename: xenial
2.安装 设置仓库 首次安装之前,需要设置 Docker 仓库。之后可以从仓库安装和更新Docker
1.更新源和安装apt 依赖包,用于通过HTTPS来获取仓库# apt-get update # apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release 2.添加软件源的GPG密钥。这里采用中科大的 curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add - 3.添加Docker软件源。同样中科大# add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
安装 Docker 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 1.再次更新源# apt-get update 2.安装 docker-ce社区版# apt-get install docker-ce docker-ce-cli containerd.io 3.验证是否安装成功# docker run hello-world 4. 这个命令会下载一个hello-world镜像并运行在容器中,打印出以下信息则安装成功 root@iZbp1aq6c9kbbexg9cxsqiZ:~# docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
卸载Docker 1.卸载依赖# apt-get remove docker docker-engine docker.io containerd runc 2.删除镜像、容器、配置文件等内容:# rm -rf /var/lib/docker
Run流程 Docker首先会从本地查找这个镜像,找到的话直接运行;找不到就去仓库上查找,找到的话返回该镜像运行
三、Docker常用命令 1.帮助命令 docker 命令 --help #显示某命令的帮助信息 docker version #显示docker的版本信息 docker info #显示docker的系统、镜像、容器信息
2.镜像命令 查看镜像 docker images
REPOSITORY:仓库源
TAG:标签(版本)
IMAGE ID:镜像的ID
CREATED:镜像创建的时间
SIZE:大小
[root ] REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 8 weeks ago 13.3 kB
搜索镜像 docker search
NAME:镜像仓库源
DESCRIPTION: 镜像的描述
OFFICIAL:是否 docker 官方发布
STARS: 类似 Github 里面的 star
AUTOMATED: 自动构建
[root ] NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 11708 [OK ] mariadb MariaDB Server is a high performing open sou… 4459 [OK ] mysql/mysql-server Optimized MySQL Server Docker images. Create… 870 [OK ]
下载镜像 docker pull
默认下载最新版,可以指定版本:docker pull 镜像名:tag
删除镜像 docker rmi
rm
删除 + i
镜像 = rmi
删除镜像
可以根据镜像ID或名字来删
[root ] REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7 8 b43c6af2ad0 4 days ago 448 MB hello-world latest feb5d9fea6a5 8 weeks ago 13.3 kB [root ] [root ]
打包镜像 docker save 镜像ID/名 > 打包后的文件名
[root]# docker save mycentos:1.0 > mycentos.tar [root]# ls mycentos.tar
加载镜像 docker load < 打包的文件
# 首先使用docker rmi mycentos:1.0删除镜像 [root]# docker rmi mycentos:1.0 [root]# docker load < mycentos.tar
3.容器命令 容器是基于镜像的,所以要先下载一个镜像
root@host:~# docker pull centos
新建容器并启动 docker run
docker run [可选参数] image# 参数 --name="Name" 容器名字,比如一个Tomcat镜像,启动多个就要给个名字区分 -d 后台运行 -it 使用交互式运行。-i交互式操作,-t终端 -p 容器端口,可与主机端口进行映射 -p ip:主机端口:容器端口 -p 主机端口:容器端口 -p 容器端口 -P 大P,随机指定端口
# 启动并进入容器,host为主机名 root@host:~# docker run -it centos bash# 进入容器后主机名变为了caa2db760d6a,镜像的ID [root@caa2db760d6a /]#
run命令的延伸:
--restart=always #容器的自动启动(容器服务启动后容器自动,相当于开机自启动) -h x.xx.xx #设置容器主机名,相当于linux的hostname命令,不同的是-h是永久设置 --dns xx.xx.xx.xx #设置容器使用的DNS服务器,因为容器也需要上网 --dns-search #DNS搜索设置 --add-host hostname:IP #注入hostname<>IP解析,相当于linux改host文件,加入--add-host www.baidu.com:127.0.0.1 当然也可以exec进去改 --rm #服务停止时自动删除(容器停止后会自动删除)
退出容器 exit #容器停止并退出 Ctrl + P + Q #容器不停止(后台运行)并退出
查看容器 docker ps
-a
:查看正在运行的+历史运行过的容器
root@host:~# docker ps root@host:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES caa2db760d6a centos "/bin/bash" 5 minutes ago Exited (0) 2 minutes ago crazy_stonebraker 6e417c0d39ee feb5d9fea6a5 "/hello" 19 hours ago Exited (0) 19 hours ago trusting_dhawan
删除容器 docker rm
# 删除指定容器,不能删除正在运行的容器。强制删除使用rm -rf docker rm 容器id# 删除所有容器 docker rm -f $(docker ps -aq)
启动容器 docker start 容器id docker restrat 容器id
停止容器 docker stop 容器id docker kill 容器id #强制停止
其他命令 查看容器日志
-f
:展示日志输出
-t
:显示时间
docker logs -f -t --tail n 容器id
查看容器中进程信息
docker top
查看镜像的元数据
docker inspect
进入当前正在运行的容器
docker exec
进入容器后开启一个新的终端
docker exec -it 容器id /bin/bash
docker attach
进入容器正在执行的终端
将容器内文件拷贝到主机
docker cp
docker cp 容器id:容器内路径 目的主机路径
提交自己的镜像
docker commit
提交容器成为一个新的镜像,和git类似
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[tag]
镜像是分层的文件,镜像运行就是容器增加了一层,而这一层是可更改的(镜像不可更改),提交=将镜像原本的层+容器层打包成一个新的镜像
Tomcat9.0镜像层文件:
Tomcat9.0镜像运行后修改webapps中的文件,进行commit成新的镜像Tomcat:v2。多了一层
四、数据卷 我们将一个项目和运行环境(JDK、Tomcat、MySQL)放在容器中运行,如果容器删了,那么容器中的数据全都会丢失(删库跑路),所以不能将MySQL数据存储在容器中
数据卷 :Docker容器的数据同步到本地(目录的挂载,将容器中目录挂载到本地目录)
容器间也可以数据共享,称为数据卷容器
1.指定路径挂载 使用命令来挂载 -v
Tomcat默认访问页面目录为 webapps/ROOT,将该目录映射到主机目录,主机目录中有index.html
-P
:映射随机端口
[root]# docker run -d -v /data/niujiaming:/usr/local /tomcat/webapps/ROOT -P --name="tomcat06" tomcat:v2
docker inspect
找到Mounts这一块,已经挂载成功
Source
:主机内地址
Destination
:容器内地址
docker ps
看到端口为49153
[root@k8s-node-201]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 27b4a04e5f89 tomcat:v2 "catalina.sh run" 8 minutes ago Up 8 minutes 0.0.0.0:49153->8080/tcp tomcat06
访问该地址
2.匿名挂载 -v
后面只指定容器目录
docker run -v /usr/local/tomcat tomcat:9 .0
3.具名挂载 -v
后面指定一个卷名 和容器目录
docker run -d -P --name tomcat07 -v juming:/usr/local/tomcat tomcat:9.0
查看所有挂载信息
[root]# docker volume ls DRIVER VOLUME NAME local juming
查看卷名挂载信息 docker容器内的卷,没有指定主机目录的话都是在 /var/lib/docker/volumes 这个目录下
[root]# docker inspect juming [ { "CreatedAt": "2021-11-23T16:59:53+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/juming/_data", "Name": "juming", "Options": null, "Scope": "local" } ]
进入主机的 /var/lib/docker/volumes/juming/_data
目录下,该目录的文件就是容器目录/usr/local/tomcat
五、数据卷容器 容器之间配置信息的传递
创建父容器 ngnix01
匿名挂载,数据卷为/usr/share/nginx/html
[root]# docker run -d -p 9555:80 --name="nginx01" -v /usr/share/nginx/html nginx
修改index.html文件内容
root@7ac95a402565:/usr/share/nginx/html# echo 'this is nginx01 container'>index.html root@7ac95a402565:/usr/share/nginx/html# cat index.html this is nginx01 container
创建子容器 nginx02
--volumes-from
:指定父容器的数据卷,这样nginx02的/usr/share/nginx/html指向nginx01的/usr/share/nginx/html
[root]# docker run -d -p 9556:80 --name="nginx02" --volumes-from nginx01 nginx
访问
nginx01端口、nginx02端口
查看nginx01容器的数据卷
查看nginx02容器的数据卷
它们两个都指向了主机的目录
六、Dockerfile 用来构建docker镜像的的构建文件(脚本)
镜像是一层层的文件,而Dockerfile中每个命令都是一层
1.创建Dockerfile FROM
:定制需要的基础镜像
VOLUME
:定义匿名数据卷,镜像中会有volume01、volume02文件夹,如果在run
的时候没有挂载数据卷,会自动挂载到匿名卷
RUN
:用于执行后面跟着的命令行命令
[root]# vim dockerfile01 [root]# cat dockerfile01 FROM nginx VOLUME ["volume01","volume02"] RUN echo 'this is nginx image' > /usr/share/nginx/html/index.html
2.构建镜像 docker build
-f
:指定文件,Docker默认指定的文件名称为Dockerfile
,如果构建文件叫这个名字,就不需要-f
-t
:镜像的名字和tag
.
:上下文路径,指docker在构建镜像时,如想要使用到本机的文件,docker build 命令得知这个路径后,会将路径下的所有内容打包。构建过程实际是由docker引擎来完成的,所以无法使用本机文件,需要将上下文路径下的文件一起打包给docker引擎使用,默认为 Dockerfile 所在的位置 (不要放无用的文件,会一起打包的,如果文件过多会造成过程缓慢)
[root]# docker build -f dockerfile01 -t niujiaming/nginx:1.0 . Sending build context to Docker daemon 3.072kB Step 1/2 : FROM nginx ---> 4f380adfc10f Step 2/2 : RUN echo 'this is nginx image' > /usr/share/nginx/html/index.html ---> Running in 95bd82f5c70d Removing intermediate container 95bd82f5c70d ---> f6838b1e004f Successfully built f6838b1e004f Successfully tagged niujiaming/nginx:1.0
查看构建的镜像
[root]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE niujiaming/nginx 1.0 f6838b1e004f 7 minutes ago 133MB
3.运行镜像 Dockerfile没有指定数据卷,run也没有指定数据卷,所以是匿名挂载
[root]# docker run -d -P niujiaming/nginx:1.0
查看容器信息
docker inspect 容器id
Mounts有数据卷信息
Dockfile指令 规则:
每个指令都必须是大写字母
执行从上到下执行
#表示注释
每个指令都会创建提交一个新的镜像层
指令
描述
语法
FROM
指定基础镜像,并且必须是第一条指令
FROM < image>[:< tag>]
MAINTAINER
设置镜像作者
MAINTAINER < name>
LABEL
为镜像指定标签
LABEL < key>=< value>
RUN
镜像构建 docker build
时执行的命令
RUN < command> | RUN [“executeable”, “param1”]
CMD
镜像运行 docker run
时执行的命令。如果写了多条则只有最后一条生效。如果在docker run
时添加命令,则会替换CMD设置的命令
同上👆
ENTRYPOINT
类似于 CMD 指令,但不会被docker run命令覆盖,而是将命令当作字符串,传递给ENTRYPOINT作为参数。例:ENTRYPOINT [“ls”,”-a”] ,docker run -l,最后执行的是ls -la
ENTRYPOINT [“< executeable>”,”< param1>”]
ADD
复制文件到镜像中。如果是压缩文件,add会自动解压。默认编译目录(上下文路径)寻找文件,dest为镜像中的绝对路径或者相对于WORKDIR 的路径
ADD < src>… < dest>
COPY
复制文件到镜像中。指令和ADD相似
同上👆
WORKDIR
镜像的工作目录
WORKDIR < Path>
VOLUME
定义匿名数据卷。启动容器时,会新建挂载点,并用镜像中的数据初始化挂载点,可以将主机目录或数据卷容器挂载到这里
VOLUME [“/dir”]
EXPOSE
暴露镜像端口。但需要启动容器时使用-P/-p映射端口,才能通过外部访问容器提供的服务
EXPOSE < port> < port> …
ONBUILD
后面跟的是其它指令,比如 RUN、COPY 等,这些指令在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
ONBUILD [INSTRUCTION]
ENV
设置镜像中的环境变量。后续的指令,就可以使用这个环境变量$key
ENV < key>=< value>…
ARG
构建参数,作用同ENV,但ARG 的环境变量仅对 Dockerfile 内有效
ARG < key>[=< value>]
一些练习 1.centos
创建dockerfile-centos
[root]FROM centosLABEL author=niujiaming ENV MYPATH=/usr/localWORKDIR $MYPATH RUN yum -y install vim \ && yum -y install net-tools CMD echo "---end---"
构建
[root]# docker build -f dockerfile-centos -t mycentos:1.0 .
运行 也可以将/bin/bash
作为CMD命令放在构建文件中
# 因为docker run 的命令为/bin/bash,覆盖了CMD echo "---end---" ,所以没有输出 [root]# docker run -it mycentos:1.0 /bin/bash # 工作目录 [root@94ce9a8571ab local]# pwd /usr/local
2.tomcat
下载tomcat、jdk压缩包
[root]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.54/bin/apache-tomcat-9.0.54.tar.gz [root]# wget https://repo.huaweicloud.com/java/jdk/8u192-b12/jdk-8u192-linux-x64.tar.gz
编写Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 FROM centosADD jdk-8u192-linux-x64.tar.gz /usr/local / ADD apache-tomcat-9.0.54.tar.gz /usr/local / RUN yum -y install vim ENV MYPATH=/usr/localWORKDIR $MYPATH ENV JAVA_HOME=/usr/local/jdk1.8.0 _192 CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar CATALINA_HOME=/usr/local/apache-tomcat-9.0 .54 CATALINA_BASH=$CATALINA_HOME PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/binEXPOSE 8080 CMD /usr/local /apache-tomcat-9.0.54/bin/startup.sh && tail -F =/usr/local /apache-tomcat-9.0.54/bin/logs/catalina.out
构建
因为构建文件名称为Dockerfile
,这里不需要指定
[root]# docker build -t mytomcat:1.0 .
启动
这里将webapps作为数据卷,/data/niujiaming下有index.html
[root]# docker run -d -p 9556:8080 --name mytomcat04 -v /data/niujiaming:/usr/local /apache-tomcat-9.0.54/webapps mytomcat:1.0
Docker全流程图
七、Docker网络 1.Docker0 使用ip addr
命令查看网卡
docker0就是docker的地址。docker使用的是桥接模式,使用的技术是veth-pair技术
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:63:5e:e7:d2 brd ff:ff:ff:ff:ff:ff inet 172.29.42.1/24 brd 172.29.42.255 scope global docker0 valid_lft forever preferred_lft forever
启动一个容器并查看它的网卡,有一个80: eth0@if81
,为172.29.42.2
[root]# docker exec -it 529ca5d42ba3 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 80: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:1d:2a:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.29.42.2/24 brd 172.29.42.255 scope global eth0 valid_lft forever preferred_lft forever
主机也会增加一个网卡81: veth702c876@if80
,这里的80指的就是容器的网卡80: eth0@if81
81: veth702c876@if80: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 8a:96:ba:26:6d:97 brd ff:ff:ff:ff:ff:ff link-netnsid 0
主机网卡81: veth702c876@if80
容器网卡80: eth0@if81
这就是前面说的veth-pair(Virtual Ethernet)技术。veth-pair就是一对虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连,所以可以通信。veth-pair可以充当一个桥梁。
查看docker网络配置
[root]# docker network ls NETWORK ID NAME DRIVER SCOPE 0701b7e4eba0 bridge bridge local
查看桥接 0701b7e4eba0
[root]# docker network inspect 0701b7e4eba0
Docker0地址
容器地址。启动容器时docker分配的ip
主机上启动的Docker容器会连接到这个Docker0虚拟网桥上,这样主机上的所有容器就通过交换机连在了一个二层网络中
graph TB;
主机host-->Docker0/172.29.42.1;
Docker0/172.29.42.1--veth-eth0-->容器1/172.29.42.2;
Docker0/172.29.42.1--veth-eth0-->容器2/172.29.42.3;
2.自定义网络
自定义网络来控制哪些容器可以相互通信
docker network ls
查看所有网络
[root]# docker network ls NETWORK ID NAME DRIVER SCOPE 0701b7e4eba0 bridge bridge local e95169f22189 host host local 6aab19df3032 none null local
网络模式
简介
bridge
桥接。此模式会为每一个容器分配IP,并将容器连接到docker0虚拟网桥,
host
使用主机地址
none
关闭了容器的网络功能
自定义网络
这3个网络是docker内置的,当我们运行一个容器需要指定网络时,可以通过--net
参数来指定容器连接的网络。默认运行已经添加了--net bridge
1.创建一个网络 docker network create [参数] 网络名
[root]# docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 网络名
查看
[root@k8s-node-201 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 0701b7e4eba0 bridge bridge local e95169f22189 host host local 6aab19df3032 none null local 4b40a9e01c65 testnet bridge local
ip addr
也会增加一个网络
2.启动容器,指定网络 [root]# docker run -d -P --name="mytomcat05" --net testnet mytomcat:1.0 [root]# docker run -d -P --name="mytomcat06" --net testnet mytomcat:1.0
docker network inspect testnet
可以看到这两个容器
通过自定义网络可以实现两个容器之间网络的互通
[root]# docker exec -it mytomcat05 ping 192.168.0.3 PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data. 64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.128 ms[root]# docker exec -it mytomcat06 ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.083 ms
3连接容器至网络 mytomcat05、mytomcat06位于192.168.0.0/16网段中
mytomcat01位于Docker0(172.29.42.0/24)网段中
那么怎么让01访问05、06(将mytomcat01 容器连接到testnet 网络中)
docker network connect 网络名 容器名
docker network connect testnet mytomcat01
查看docker network inspect testnet
mytomcat01容器被加到testnet网络中了(相当于用一根网线把一台机器接入另一个局域网中)
八、Docker Compose 定义和运行多个 Docker容器的应用,负责实现对Docker容器集群的快速编排
使用一个Dockerfile文件,可以定义一个单独的应用容器,但是有时需要多个容器相互配合来完成某项任务,例如要实现Web项目,需要Web服务容器,还要数据库容器、负载均衡容器等
compose满足了这样的需求,用户通过一个单独的docker-compose.yml
模板文件来定义一组相关联的应用容器为一个项目(project )
核心概念:
服务(service) :一个应用的容器,比如web、redis、mysql,服务=容器,一堆容器组成一个项目
项目(project) :多个服务共同组成的完整业务单元。在docker-compose.yml
中定义,定义项目中用到的所有服务
docker-compose.yml
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code - logvolume01:/var/log links: - redis redis: image: redis volumes: logvolume01: {}
1.安装Compose 下载二进制文件
[root]# curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s) -$(uname -m) " -o /usr/local /bin/docker-compose
2.授权
[root]# chmod +x /usr/local /bin/docker-compose
3.测试
[root]# docker-compose version docker-compose version 1.18.0, build 8dd22a9 docker-py version: 2.6.1 CPython version: 3.6.8 OpenSSL version: OpenSSL 1.0.2k-fips 26 Jan 2017
2.使用Compose
docker-compose.yml
定义应用所需要的环境(web、redis)
version:版本
services:服务,可包含多个
服务名(要唯一)
image:创建当前这个服务使用的镜像
ports:端口映射,注意格式
version: '3' services: tomcat: image: "tomcat:8.0" ports: - "9555:8080"
运行docker-compose
docker-compose up
启动这个项目的所有服务。默认前台启动
docker ps -a
查看
[root]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5c9ed5cbd86d tomcat:8.0 "catalina.sh run" 3 minutes ago Exited (143) 2 minutes ago composetest_tomcat_1
也会创建一个相应的网络,yml中所有的服务都位于该网络下
[root]# docker network ls NETWORK ID NAME DRIVER SCOPE 101dbead5e52 composetest_default bridge local
3.yml模板命令 标准模板文件应该包含version、services、networks 三大部分,最关键的是services和networks两个部分
version 版本号
image 指定服务的镜像名称.。想当于run image
services: tomcat: image: "tomcat:8.0"
build 服务除了可以基于指定的镜像,还可以基于Dockerfile
compose会根据build
中的Dockerfile自动构建镜像,然后使用镜像启动服务
services: webapp01: build: ./dir webapp02: build: context: ./dir dockerfile: Dockerfile02
container_name Compose的容器默认名称格式是:项目名称_ 服务名称_序号
自定义容器名称。相当于run –name
services: tomcat01: container_name: tomcat01 image: "tomcat:8.0"
ports 映射端口。相当于run -p
services: tomcat: image: "tomcat:8.0" ports: - "9555:8080"
volumes 完成主机与容器目录数据卷共享。相当于run -v
services: tomcat: image: "tomcat:8.0" volumes: - /usr/local/tomcat/webapps - /opt/data:/usr/local/tomcat/webapps - datavolume:/var/lib/conf volumes: datavolume:
networks 配置容器连接的网络,需引用顶级 networks 下的条目。相当于run –net
services: tomcat01: image: "tomcat:8.0" networks: - net01 tomcat02: image: "tomcat:8.0" networks: - net01 networks: net01:
command 覆盖容器 启动后默认执行的命令
services: tomcat01: image: "tomcat:8.0" command: "/usr/local/tomcat/bin/startup.sh "
environment 添加环境变量,可以用数组或字典两种方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 services: mysql01: image: "mysql:5.7" container_name: mysql01 ports: - "3306:3306" volumes: - mysqldata:/var/lib/mysql - mysqlconf:/etc/mysql environment: - MYSQL_ROOT_PASSWORD=123456 - SHOW=true environment: MYSQL_ROOT_PASSWORD:123456 SHOW:"true" volumes: mysqldata: mysqlconf:
env_file 从文件中获取环境变量,可以指定一个文件路径或路径列表,其优先级低于 environment 指定的环境变量
如果通过docker-compose -f 文件名
来指定yml模板文件的话,env_file
变量的路径会基于模板文件的路径
services: mysql01: image: "mysql:5.7" container_name: mysql01 ports: - "3306:3306" environment: - ./mysql.env
环境变量文件格式,类似properties
MYSQL_ROOT_PASSWORD =123456
depends_on 设置依赖关系,写的是服务名
web服务依赖于mysql和redis,所以要先启动mysql和redis
version: "3" services: web: build: . depends_on: - mysql - redis redis: image:redis mysql: image:mysql:5.7
healthcheck 通过命令检查容器(服务)是否健康运行
healthcheck: test: ["CMD" ,"curl" ,"-f" ,"http://localhost" ] interval: 1m30s timeout: 10s retries: 3
sysctls 配置容器内核参数,可以使用数组或字典格式
sysctls: net.core.somaxconn: 1024 net.ipv4.tcp_syncookies: 0 sysctls: - net.core.somaxconn=1024 - net.ipv4.tcp_syncookies=0
ulimits 修改容器内系统的最大进程数
ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000
4.compose常用指令 docker-compose [-f=<agr>] [option] [COMMAND] [ARGS...]
-f
:指定compose模板文件,默认是当前目录的的docker-compose.yml
-p
:指定项目名称,默认使用当前目录的名称作为项目名
--verbose
:输出更多调试信息
up 自动完成包括构建镜像,创建服务,启动服务,并关联服务相关容器的一系列操作。
大部分时候都可以直接通过该命令来启动一个项目
-d
:后台运行
service
:某个服务,默认启动所有服务
docker-compose up [options] [service...]
down 关闭所有的docker-compose服务,并移除网桥
stop 关闭所有的docker-compose服务,不会移除网桥
rm 删除(停止状态的)服务容器
-f
:强制删除,包括正在运行的
-v
:删除容器所挂载的数据卷
docker-compose rm [option] [service...]
exec 和docker exec
一样,进入容器,但是使用的是服务名,也不需要使用-it
docker-compose exec 服务名 bash
ps 列出该项目 中所有容器,与docker ps
不同
top 查看服务容器内运行的进程
start、restart 启动、重启项目中的服务
-t
:指定重启前停止容器的超时(默认10秒)
docker-compose restart [option] [service...]
练习 部署mysql和后台应用
mysql采用dockerfile:
FROM mysql:5.7 ENV WORK_DIR=/usr/local/mysqlENV MYSQL_ROOT_PASSWORD=1351740185 ENV AUTO_RUN_DIR /docker-entrypoint -initdb.d WORKDIR $WORK_DIR COPY dian-jz.sql $AUTO_RUN_DIR RUN chmod a+x $AUTO_RUN_DIR /dian-jz.sql EXPOSE 3306
后台:连接数据采用的是数据库服务名:3306
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 version: '3' services: jz01: image: "java:8" volumes: - /data/niujiaming/jz/java/jz-0.0.1-SNAPSHOT.jar:/jz.jar - /data/niujiaming/jz/java/logs:/logs ports: - "9555:8002" networks: - jznet depends_on: - jzmysql entrypoint: java -jar jz.jar jzmysql: build: context: ./mysql volumes: - /data/niujiaming/jz/mysql/data:/var/lib/mysql - /data/niujiaming/jz/mysql/logs:/var/log/mysql ports: - "3307:3306" networks: - jznet networks: jznet: