Loading

初识Docker

Docker

Docker安装前置条件

修改配置

vim /etc/selinux/config

重启linux

Docker的基本组成

img

镜像(image)

​ docker镜像就好比是一个目标,可以通过这个目标来创建容器服务,通过这个镜像可以创建多个容器。

容器(container)

​ Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建。

仓库(repository)

​ 仓库就是用来存放镜像的地方。仓库分为公有仓库和私有仓库。

底层原理

为什么Docker比Vm快

​ 1、docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在cpu、内存利用率上docker将会在效率上有明显的优势。

​ 2、docker利用的是宿主机的内容,而不需要Guest OS。

​ 因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。从而避免引导、加载操作系统内核等比较费时费资源的过程。

Docker常用命令

帮助命令

docker version   #显示docker的版本信息 
docker info      #显示docker的系统信息,包括镜像和容器的数量
docker --help    #帮助命令

镜像命令

docker images    #查看所有本地主机上的镜像,可以使用docker image li代替
docker search    #搜索镜像
docker pull      #下载镜像
docker rmi       #删除镜像

容器命令

docker run 镜像id    #新建容器并启动
 -d                 #后台进程运行
 --name             #命名容器名
 -p                 #指定映射端口
 -e                 #修改配置文件或者环境配置
 
docker ps           #列出所有运行的容器
 -a, --all     	    #列出当前正在运行的容器 + 带出历史运行过的容器
 -n=?, --last int   #列出最近创建的?个容器 ?为1则只列出最近创建的一个容器,为2则列出2个
 -q, --quiet        #只列出容器的编号
 
docker rm 容器id     #删除指定的容器
docker rm -f $(docker ps -aq)  	 #删除所有的容器
docker ps -a -q|xargs docker rm  #删除所有的容器

docker start 容器id   #启动容器
docker restart 容器id #重启容器
docker stop 容器id    #停止当前正在运行的容器
docker kill 容器id    #强制停止当前容器

exit      #容器直接退出
ctrl+P+Q  #容器不停止退出

docker logs -t --tail n 容器id #查看n行日志
docker logs -ft 容器id #跟着日志

docker inspect 容器id  #查看镜像的元数据(挂载卷等)

docker exec -it 容器id /bin/bash   #进入当前容器后开启一个新的终端,可以在里面操作。
docker attach 容器id    #进入容器正在执行的终端

docker cp 容器id:容器内路径 主机目的路径  #从容器内拷贝到主机上

docker commit m="描述信息" -a="作者" 容器id 目标镜像名:[版本TAG] #提交容器成为一个新的副本

docker update redis --restart=always #开机自启动redis

容器数据卷

什么是容器数据卷

​ 容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地,这就是卷技术。目录的挂载,将我们容器内的目录挂载到Linux上面。

使用数据卷

docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口

实战:安装MySql

# 获取mysql镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载,安装启动mysql,需要配置密码!!
docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

具名和匿名挂载

匿名挂载

-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume(卷)的情况
docker volume ls
DRIVER              VOLUME NAME # 容器内的卷名(匿名卷挂载)
local               21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local               b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!

具名挂载

docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
	-P:表示随机映射端口
# 查看所有的volume(卷)的情况
$ docker volume ls                  
DRIVER              VOLUME NAME
local               21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local               b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
local               juming-nginx #多了一个名字

# 通过 -v 卷名:查看容器内路径
# 查看一下这个卷
$ docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2020-05-23T13:55:34+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下,如果指定了目录,docker volume ls是查看不到的。

区分三种挂载方式

# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径			#匿名挂载
-v 卷名:容器内路径		  #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的

Dockerfile

​ Dockerfile就是用来构建docker镜像的构建文件,通过这个脚本可以生成镜像,镜像是一层层的,脚本是一个个的命令,每个命令都是一层。

​ 构建步骤:

​ 1、编写一个dockerfile文件

​ 2、docker build 构建称为一个镜像

​ 3、docker run 运行镜像

​ 4、docker push发布镜像(DockerHub、阿里云仓库)

# 创建一个dockerfile文件
# 文件中的内容:指令(大写)+参数
vim dockerfile1
	FROM centos                      # 当前这个镜像是以centos为基础的
	VOLUME ["vokume01","volume02"]   # 挂载卷的卷目录列表(多个目录)
	CMD echo "------end------"       # 输出以下用于测试
	CMD /bin/bash                    # 默认走bash控制台
	
# 这里的每个命令,就是镜像的一层
# 构建出这个镜像
docker build -f dockerfile1 -t csp/centos .
	-f            # 代表file,指dockerfile当文件的地址
	-t            # 代表target,指目标目录(注意csp镜像名前不能加斜杠'/')
	.             # 表示生成在当前目录下

多个mysql实现数据共享

$ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

$ docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7

# 这个时候,可以实现两个容器数据同步!

结论:

​ 容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的。

构建过程

1、每个保留关键字都是必须是大写字母

2、顺序执行从上到下

3、每一个指令都会创建提交一个新的镜像层,并提交。

DockerFile的指令

FROM				# from:基础镜像,一切从这里开始构建
MAINTAINER			# maintainer:镜像是谁写的, 姓名+邮箱
RUN					# run:镜像构建的时候需要运行的命令
ADD					# add:步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR				# workdir:镜像的工作目录
VOLUME				# volume:挂载的目录
EXPOSE				# expose:保留端口配置
CMD					# cmd:指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT			# entrypoint:指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD				# onbuild:当构建一个被继承DockerFile这个时候就会运行onbuild的指令,触发指令
COPY				# copy:类似ADD,将我们文件拷贝到镜像中
ENV					# env:构建的时候设置环境变量!

​ 我们平时拿到一个镜像,可以用“docker history 镜像id”研究一下是什么做的。

实战:Tomcat镜像

1、准备镜像文件

​ 准备tomcat和jdk到当前目录,编写好README

2、编写dockerfile

$ vim dockerfile
FROM centos 								    # 基础镜像centos
MAINTAINER CSP<XXX@qq.com>					    # 作者
COPY README /usr/local/README 					# 复制README文件
ADD jdk-8u231-linux-x64.tar.gz /usr/local/ 		# 添加jdk,ADD 命令会自动解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local/ 	# 添加tomcat,ADD 命令会自动解压
RUN yum -y install vim							# 安装 vim 命令
ENV MYPATH /usr/local 							# 环境变量设置 工作目录
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_231 			# 环境变量: JAVA_HOME环境变量
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 	# 环境变量: tomcat环境变量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35

# 设置环境变量 分隔符是:
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin 	

EXPOSE 8080 										# 设置暴露的端口

CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out   # 设置默认命令

3、构建镜像

# 因为dockerfile命名使用默认命名 因此不用使用-f 指定文件
$ docker build -t mytomcat:0.1 .

4、run镜像

# -d:后台运行 -p:暴露端口 --name:别名 -v:绑定路径 
$ docker run -d -p 8080:8080 --name tomcat01 
-v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test 
-v /home/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.1

5、访问测试

$ docker exec -it 自定义容器的id /bin/bash

$ cul localhost:8080

6、发布项目

Docker网络

​ 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术。

veth-pair相关知识:https://www.cnblogs.com/bakari/p/10613710.html

网络模型

img

​ 所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip。

​ Docker使用的是Linux的桥接,宿主机是一个Docker容器的网桥docker0。

​ Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)。只要容器删除,对应的网桥一对就没了。

自定义网络

docker network
connect     -- Connect a container to a network
create      -- Creates a new network with a name specified by the
disconnect  -- Disconnects a container from a network
inspect     -- Displays detailed information on a network
ls          -- Lists all the networks created by the user
prune       -- Remove all unused networks
rm          -- Deletes one or more networks

查看所有的docker网络

docker network ls

网络模式

1、bridge:桥接docker(默认,自己创建也是用bridge模式)

2、none:不配置网络,一般不用

3、host:和所有主机共享网络

4、container:容器网络连通(用的少,局限很大)

# 我们直接启动的命令 --net bridge,而这个就是我们得docker0
# bridge就是docker0
$ docker run -d -P --name tomcat01 tomcat
等价于 => docker run -d -P --name tomcat01 --net bridge tomcat

# docker0,特点:默认,域名不能访问。 --link可以打通连接,但是很麻烦!
# 我们可以自定义一个网络
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

# 启动两个tomcat,再次查看网络情况
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat

# 查看网络情况
docker network inspect mynet

​ 在自定义的网络下,服务可以互相ping通,不用使用-link。

​ 假设要跨网络操作别人,需要使用docker network connect连通。

实战:部署Redis集群

img

# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建6个redis配置
for port in $(seq 1 6);
do
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 通过脚本运行6个redis
for port in $(seq 1 6);
docker run -p 637${port}:6379 -p 1667${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker exec -it redis-1 /bin/bash
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379  --cluster-replicas 1

限制docker容器与宿主机以外的机器互通

1、创建一个新链接BEFORE_DOCKER

iptables -N BEFORE_DOCKER

2、配置BEFORE_DOCKER只能连接宿主机172.20.0.1

iptables -I BEFORE_DOCKER -j DROP
iptables -I BEFORE_DOCKER -i ens160 -s 172.20.0.1 -j ACCEPT

3、创建一个c断为172.20.0.0/24的docker网络docker1

docker network create --subnet=172.20.0.0/24 --opt "com.docker.network.bridge.name"="docker1" docker1

4、将docker网络docker1的外发规则绑定到BEFORE_DOCKER

iptables -I FORWARD -o docker1 -j BEFORE_DOCKER

保存镜像

docker save -o django_uwsgi-v3.img django_uwsgi:v3

加载镜像

docker load --input django_uwsgi-v3.img
posted @ 2021-03-01 11:34  c5p1ng  阅读(80)  评论(0编辑  收藏  举报