docker 基础篇

帮助命令

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

镜像命令

docker images #查看所有本地主机上的镜像 可以使用docker image ls代替

docker search #搜索镜像

容器命令

docker pull #下载镜像 docker image pull

docker rmi #删除镜像 docker image rm

docker images

docker images -a  #列出所有镜像详细信息
docker images -aq #列出所有镜像的id
docker search mysql #查询网上的mysql的镜像 
#  --filter=STARS=3000 #过滤,搜索出来的镜像收藏STARS数量大于3000的

#等价于
docker pull tomcat:8
docker pull docker.io/library/tomcat:8

docker rmi -f 镜像id #删除指定id的镜像
docker rmi -f $(docker images -aq) #删除全部的镜像
docker stop $(docker ps -a -q) #停止所有的容器
docker pull centos        #docker中下载centos
docker run 镜像id         #新建容器并启动
docker container list -a  # 查看所有的容器
docker ps -a              # 查看所有的容器
docker rm 容器id          #删除指定容器
docker start 容器id	      #启动容器
docker restart 容器id     #重启容器
docker stop 容器id	      #停止当前正在运行的容器
docker kill 容器id	      #强制停止当前容器
docker run [可选参数] image | docker container run [可选参数] image 
#参书说明
--name="Name"		#容器名字 tomcat01 tomcat02 用来区分容器
-d					#后台方式运行
-it 				#使用交互方式运行,进入容器查看内容
-p					#指定容器的端口 -p 8080(宿主机):8080(容器)
		-p ip:主机端口:容器端口
		-p 主机端口:容器端口(常用)
		-p 容器端口
		容器端口
-P(大写) 				随机指定端口
docker run -it centos /bin/bash # 测试、启动并进入容器

exit #从容器退回主机

docker ps 命令  		#列出当前正在运行的容器 还没退出的(exit)
  -a, --all     	 #列出当前正在运行的容器 + 带出历史运行过的容器
  -n=?, --last int   #列出最近创建的?个容器 ?为1则只列出最近创建的一个容器,为2则列出2个
  -q, --quiet        #只列出容器的编号

退出容器

exit 		#容器直接退出
ctrl +P +Q  #容器不停止退出 	---注意:这个很有用的操作

删除容器

docker rm 容器id   				#删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -rf
docker rm -f $(docker ps -aq)  	 #删除所有的容器
docker ps -a -q|xargs docker rm  #删除所有的容器

后台启动命令

docker run -d centos #这都是看不到信息的

# 问题docker ps. 发现centos 停止了
# 常见的坑,docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

查看日志

docker logs --help
Options:
      --details        Show extra details provided to logs 
*  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
*      --tail string    Number of lines to show from the end of the logs (default "all")
*  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
➜  ~ docker run -d centos /bin/sh -c "while true;do echo 6666;sleep 1;done" #模拟日志      
#显示日志
-tf		#显示日志信息(一直更新)
--tail number #需要显示日志条数
docker logs -t --tail n 容器id #查看n行日志
docker logs -ft 容器id #跟着日志

查看容器进程信息

#查看容器中进程信息ps
docker top 容器id

查看镜像的元数据

docker inspect 容器id
docker inspect 镜像id

进入当前正在运行的容器

# 方式一
# 进入当前正在运行的容器
docker exec -it 容器id bashshell

# 方式二
docker attach 容器id
#测试
docker attach 55321bcae33d 
正在执行当前的代码...
区别
#docker exec #进入当前容器后开启一个新的终端,可以在里面操作。(常用)
#docker attach # 进入容器正在执行的终端

从容器内拷贝到主机上

#先进入到容器中
docker exec -it 56a5583b25b4 /bin/bash
#再创建一个新文件
echo "hello" > hello.java # "hello"是内容 hello.java是文件名(souce命令用不了)
#测试文件是否存在了
cat hello.java 

#将容器中的文件拷贝到主机上
# docker cp 容器名:容器内文件 主机上的路径
docker cp 9035020356a4:/java.java /home

命令大全

attach      Attach local standard input, output, and error streams to a running container
  #当前shell下 attach连接指定运行的镜像
  build       Build an image from a Dockerfile # 通过Dockerfile定制镜像
  commit      Create a new image from a container's changes #提交当前容器为新的镜像
  cp          Copy files/folders between a container and the local filesystem #拷贝文件
  create      Create a new container #创建一个新的容器
  diff        Inspect changes to files or directories on a container's filesystem #查看docker容器的变化
  events      Get real time events from the server # 从服务获取容器实时时间
  exec        Run a command in a running container # 在运行中的容器上运行命令
  export      Export a container's filesystem as a tar archive #导出容器文件系统作为一个tar归档文件[对应import]
  history     Show the history of an image # 展示一个镜像形成历史
  images      List images #列出系统当前的镜像
  import      Import the contents from a tarball to create a filesystem image #从tar包中导入内容创建一个文件系统镜像
  info        Display system-wide information # 显示全系统信息
  inspect     Return low-level information on Docker objects #查看容器详细信息
  kill        Kill one or more running containers # kill指定docker容器
  load        Load an image from a tar archive or STDIN #从一个tar包或标准输入中加载一个镜像[对应save]
  login       Log in to a Docker registry #
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

作业一:Docker 安装Nginx

# 这种绑定宿主机端口的 是可以后台运行的 不会自动关闭
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
docker run -d --name nginx01 -p 3344:80 nginx

docker exec -it nginx01 /bin/bash #进入容器 可用name进入e

whereis nginx	#找到nginx位置

# 跟宿主机绑定端口之后 之前ps start restart都可以使用测试了

作业二:用docker 来装一个tomcat

# 之前的启动都是后台,停止了容器,容器还是可以查到, docker run -it --rm 镜像名 一般是用来测试,用完就删除

--rm       Automatically remove the container when it exits 用完即

#以后台方式,暴露端口方式,启动运行
docker run -d -p 8080:8080 --name tomcat01 tomcat

#默认tomcat——》webapp没有可执行文件 可将webapp.dist下的文件复制到 webapps下
cp -r webapps.dist/ webapps

# 确保服务器的端口号开启 8080

#测试访问有没有问题
curl localhost:8080

作业三:部署elasticsearch+kibana

# es 暴露的端口很多!
# es 十分耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork ? 网络配置

# 启动elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

docker stats  # 查看docker容器使用内存情况

# -e环境配置
#测试成功就关掉elasticSearch,可以添加内存的限制,修改配置文件 -e 环境配置修改
➜  ~ docker rm -f d73ad2f22dd3            # stop命令也行                               
➜  ~ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

Portainer 可视化面板安装

docker run -d -p 8080:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

Rancher(CI/CD再用)

Docker图形化界面管理工具!提供一个后台面板供我们操作!

# 安装命令
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:9000 \
> --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

Unable to find image 'portainer/portainer:latest' locally
latest: Pulling from portainer/portainer
d1e017099d17: Pull complete 
a7dca5b5a9e8: Pull complete 
Digest: sha256:4ae7f14330b56ffc8728e63d355bc4bc7381417fa45ba0597e5dd32682901080
Status: Downloaded newer image for portainer/portainer:latest
81753869c4fd438cec0e31659cbed0d112ad22bbcfcb9605483b126ee8ff306d
#查看镜像分层的方式可以通过
docker image inspect 命令

[
    {
        "Id": "sha256:f9b9909726890b00d2098081642edf32e5211b7ab53563929a47f250bcdc1d7c",
        "RepoTags": [
            "redis:latest"
        ],
        "RepoDigests": [
            "redis@sha256:399a9b17b8522e24fbe2fd3b42474d4bb668d3994153c4b5d38c3dafd5903e32"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2020-05-02T01:40:19.112130797Z",
        "Container": "d30c0bcea88561bc5139821227d2199bb027eeba9083f90c701891b4affce3bc",
        "ContainerConfig": {
            "Hostname": "d30c0bcea885",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.0.1",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.1.tar.gz",
                "REDIS_DOWNLOAD_SHA=b8756e430479edc162ba9c44dc89ac394316cd482f2dc6b91bcd5fe12593f273"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"redis-server\"]"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:704c602fa36f41a6d2d08e49bd2319ccd6915418f545c838416318b3c29811e0",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "18.09.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "6379/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.0.1",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.0.1.tar.gz",
                "REDIS_DOWNLOAD_SHA=b8756e430479edc162ba9c44dc89ac394316cd482f2dc6b91bcd5fe12593f273"
            ],
            "Cmd": [
                "redis-server"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:704c602fa36f41a6d2d08e49bd2319ccd6915418f545c838416318b3c29811e0",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 104101893,
        "VirtualSize": 104101893,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/adea96bbe6518657dc2d4c6331a807eea70567144abda686588ef6c3bb0d778a/diff:/var/lib/docker/overlay2/66abd822d34dc6446e6bebe73721dfd1dc497c2c8063c43ffb8cf8140e2caeb6/diff:/var/lib/docker/overlay2/d19d24fb6a24801c5fa639c1d979d19f3f17196b3c6dde96d3b69cd2ad07ba8a/diff:/var/lib/docker/overlay2/a1e95aae5e09ca6df4f71b542c86c677b884f5280c1d3e3a1111b13644b221f9/diff:/var/lib/docker/overlay2/cd90f7a9cd0227c1db29ea992e889e4e6af057d9ab2835dd18a67a019c18bab4/diff",
                "MergedDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/merged",
                "UpperDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/diff",
                "WorkDir": "/var/lib/docker/overlay2/afa1de233453b60686a3847854624ef191d7bc317fb01e015b4f06671139fb11/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:c2adabaecedbda0af72b153c6499a0555f3a769d52370469d8f6bd6328af9b13",
                "sha256:744315296a49be711c312dfa1b3a80516116f78c437367ff0bc678da1123e990",
                "sha256:379ef5d5cb402a5538413d7285b21aa58a560882d15f1f553f7868dc4b66afa8",
                "sha256:d00fd460effb7b066760f97447c071492d471c5176d05b8af1751806a1f905f8",
                "sha256:4d0c196331523cfed7bf5bafd616ecb3855256838d850b6f3d5fba911f6c4123",
                "sha256:98b4a6242af2536383425ba2d6de033a510e049d9ca07ff501b95052da76e894"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

commit镜像

"这样新增的副本比下下来的 镜像 强 有你增加的额外的功能"
docker commit 提交容器成为一个新的副本

# 命令和git原理类似
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[版本TAG]

# 1、启动一个默认的tomcat
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:8080 tomcat
de57d0ace5716d27d0e3a7341503d07ed4695ffc266aef78e0a855b270c4064e

# 2、发现这个默认的tomcat 是没有webapps应用,官方的镜像默认webapps下面是没有文件的!
#docker exec -it 容器id /bin/bash
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it de57d0ace571 /bin/bash
root@de57d0ace571:/usr/local/tomcat# 

# 3、从webapps.dist拷贝文件进去webapp
root@de57d0ace571:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@de57d0ace571:/usr/local/tomcat# cd webapps
root@de57d0ace571:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

# 4、将操作过的容器通过commit调教为一个镜像!我们以后就使用我们修改过的镜像即可,而不需要每次都重新拷贝webapps.dist下的文件到webapps了,这就是我们自己的一个修改的镜像。
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -a="kuangshen" -m="add webapps app" 容器id tomcat02:1.0

[root@iz2zeak7sgj6i7hrb2g862z ~]# docker commit -a="csp提交的" -m="add webapps app" de57d0ace571 tomcat02.1.0
sha256:d5f28a0bb0d0b6522fdcb56f100d11298377b2b7c51b9a9e621379b01cf1487e

[root@iz2zeak7sgj6i7hrb2g862z ~]# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
tomcat02.1.0          latest              d5f28a0bb0d0        14 seconds ago      652MB
tomcat                latest              1b6b1fe7261e        5 days ago          647MB
nginx                 latest              9beeba249f3e        5 days ago          127MB
mysql                 5.7                 b84d68d0a7db        5 days ago          448MB
elasticsearch         7.6.2               f29a1ee41030        8 weeks ago         791MB
portainer/portainer   latest              2869fc110bf7        2 months ago        78.6MB
centos                latest              470671670cac        4 months ago        237MB
hello-world           latest              bf756fb1ae65        4 months ago        13.3kB

docker 进阶篇

容器数据卷

“卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!”

方式一 :直接使用命令挂载 -v

-v, --volume list             Bind mount a volume
docker run -it -v 主机目录:容器内目录  -p 主机端口:容器内端口
# /home/ceshi:主机home目录下的ceshi文件夹  映射:centos容器中的/home
docker run -it -v /home/ceshi:/home centos /bin/bash
#这时候主机的/home/ceshi文件夹就和容器的/home文件夹关联了,二者可以实现文件或数据同步了

#通过 docker inspect 容器id 查看
docker inspect 6064c490c371

#这是查看容器的信息的 Mounts就是挂载的信息
"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/ceshi", #本地
                "Destination": "/home",  #容器
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

再来测试!

1、停止容器

2、宿主机修改文件

3、启动容器

4、容器内的数据依旧是同步的

好处:我们以后修改只需要在本地修改即可,容器内会自动同步!

实战 安装MYSQL

# 获取mysql镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载 #安装启动mysql,需要配置密码的,这是要注意点!
# 参考官网hub 
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#启动我们得
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
-- name 容器名字
$ docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql03 mysql:5.7
# 启动成功之后,我们在本地使用sqlyog来测试一下
# sqlyog-连接到服务器的3306--和容器内的3306映射 
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!

假设我们将包含mysql的容器删除时,

发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能。

具名和匿名挂载

# 匿名挂载
-v 容器内路径!
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 查看所有的volume(卷)的情况
$ docker volume ls    
DRIVER              VOLUME NAME # 容器内的卷名(匿名卷挂载)
local               21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local               b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c

# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!
# 具名挂载 -P:表示随机映射端口
$ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
9663cfcb1e5a9a1548867481bfddab9fd7824a6dc4c778bf438a040fe891f0ee
# 查看所有的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 是查看不到的


#拓展
# 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

初识Dockerfile

**Dockerfile 就是用来构建docker镜像的构建文件!命令脚本!先体验一下!

通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层!**

# 创建一个dockerfile文件,名字可以随便 建议Dockerfile
# 文件中的内容: 指令(大写) + 参数
$ vim dockerfile1
    FROM centos                     # 当前这个镜像是以centos为基础的
    VOLUME ["volume01","volume02"]     # 挂载卷的卷目录列表(多个目录)
    CMD echo "-----end-----"        # 输出一下用于测试
    CMD /bin/bash                    # 默认走bash控制台
# 这里的每个命令,就是镜像的一层!
# 构建出这个镜像 
-f dockerfile1             # f代表file,指这个当前文件的地址(这里是当前目录下的dockerfile1)
-t caoshipeng/centos     # t就代表target,指目标目录(注意caoshipeng镜像名前不能加斜杠‘/’)
.                         # 表示生成在当前目录下 -t后一定要加个目录 要不然要炸
$ docker build -f dockerfile1 -t lisen/centos .
Sending build context to Docker daemon   2.56kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
8a29a15cefae: Already exists 
Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Status: Downloaded newer image for centos:latest
 ---> 470671670cac
Step 2/4 : VOLUME ["volume01","volume02"]             # 卷名列表
 ---> Running in c18eefc2c233
Removing intermediate container c18eefc2c233
 ---> 623ae1d40fb8
Step 3/4 : CMD echo "-----end-----"                    # 输出 脚本命令
 ---> Running in 70e403669f3c
Removing intermediate container 70e403669f3c
 ---> 0eba1989c4e6
Step 4/4 : CMD /bin/bash
 ---> Running in 4342feb3a05b
Removing intermediate container 4342feb3a05b
 ---> f4a6b0d4d948
Successfully built f4a6b0d4d948
Successfully tagged caoshipeng/centos:latest


# 查看自己构建的镜像
$ docker images

# 带volume01 带volume02 匿名挂载目录
lrwxrwxrwx   1 root root   7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root 360 Sep  3 01:26 dev
drwxr-xr-x   1 root root  66 Sep  3 01:26 etc
drwxr-xr-x   2 root root   6 May 11  2019 home
lrwxrwxrwx   1 root root   7 May 11  2019 lib -> usr/lib
lrwxrwxrwx   1 root root   9 May 11  2019 lib64 -> usr/lib64
drwx------   2 root root   6 Aug  9 21:40 lost+found
drwxr-xr-x   2 root root   6 May 11  2019 media
drwxr-xr-x   2 root root   6 May 11  2019 mnt
drwxr-xr-x   2 root root   6 May 11  2019 opt
dr-xr-xr-x 105 root root   0 Sep  3 01:26 proc
dr-xr-x---   2 root root 162 Aug  9 21:40 root
drwxr-xr-x  11 root root 163 Aug  9 21:40 run
lrwxrwxrwx   1 root root   8 May 11  2019 sbin -> usr/sbin
drwxr-xr-x   2 root root   6 May 11  2019 srv
dr-xr-xr-x  13 root root   0 Apr 16 12:09 sys
drwxrwxrwt   7 root root 145 Aug  9 21:40 tmp
drwxr-xr-x  12 root root 144 Aug  9 21:40 usr
drwxr-xr-x  20 root root 262 Aug  9 21:40 var
drwxr-xr-x   2 root root   6 Sep  3 01:26 volume01
drwxr-xr-x   2 root root   6 Sep  3 01:26 volume02

exit #退出并查看容器信息 
docker inspect 容器id
# source是挂载上去了
"Mounts": [
            {
                "Type": "volume",
                "Name": "4d2fca7d6579e58a130f968a091839b1915f07c2e8d6d3a99f2786b029394a7c",
                "Source": "/var/lib/docker/volumes/4d2fca7d6579e58a130f968a091839b1915f07c2e8d6d3a99f2786b029394a7c/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "0c0adeb227565bca183976848dd09d51637965fc2f20a8cce085fa89fd9af1ce",
                "Source": "/var/lib/docker/volumes/0c0adeb227565bca183976848dd09d51637965fc2f20a8cce085fa89fd9af1ce/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

数据卷容器!

# 测试 启动3个容器,通过刚才自己写的镜像启动
# 创建docker01
docker run -it --name docker01 caoshipeng/centos

# 不关闭该容器退出
CTRL + Q + P   

# 创建docker02: 并且让docker02 继承 docker01
docker run -it --name docker02 --volumes-from docker01 caoshipeng/centos

# 在docker02中的挂载的目录添加文件 docker02都会同步的
没有挂载的目录 不会同步的

# 再新建一个docker03同样继承docker01
docker run -it --name docker03 --volumes-from docker01 caoshipeng/centos
cd volume01    #进入volume01 查看确实是同步docker01的数据


[root@lisen /]# docker run -it --name docker03 --volumes-from docker01 caoshipeng/centos
[root@5faa658c89b3 /]#
[root@5faa658c89b3 /]#
[root@5faa658c89b3 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01
[root@5faa658c89b3 /]# cd volume01/
[root@5faa658c89b3 volume01]# ls
test.txt


#现在是三个容器
[root@lisen /]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
5faa658c89b3        caoshipeng/centos   "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                       docker03
4a8e7af9df0e        caoshipeng/centos   "/bin/sh -c /bin/bash"   9 minutes ago        Up 9 minutes                            docker02
746d258bf8fc        caoshipeng/centos   "/bin/sh -c /bin/bash"   12 minutes ago       Up 12 minutes                           docker01

#删除容器docker01 其他容器的数据还是存在的
[root@lisen /]# docker rm -f 746d258bf8fc
746d258bf8fc
[root@lisen /]#
[root@lisen /]#
[root@lisen /]# docker attach 4a8e7af9df0e
[root@4a8e7af9df0e volume01]# ls
test.txt

# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试发现:数据依旧保留在docker02和docker03中没有被删除

多个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

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

结论:

容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的

DockerFile

是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

  • 1、 编写一个dockerfile文件
  • 2、 docker build 构建称为一个镜像
  • 3、 docker run运行镜像
  • 4、 docker push发布镜像(DockerHub 、阿里云仓库)
    网上的DockerFile很多

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,那我们也可以!

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:构建的时候设置环境变量!

实战测试

scratch 镜像

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20200504" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-05-04 00:00:00+01:00"
CMD ["/bin/bash"]

Docker Hub 中 99%的镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建。

创建一个自己的centos 自定义 文件中# 号注释都是要删除的

# 1./home下新建dockerfile目录
mkdir dockerfile
# 2. dockerfile目录下新建mydockerfile-centos文件
vim mydockerfile-centos
# 3.编写Dockerfile配置文件
FROM centos                            # 基础镜像是官方原生的centos
MAINTAINER                             # 作者
ENV MYPATH /usr/local                # 配置环境变量的目录 
WORKDIR $MYPATH                        # 将工作目录设置为 MYPATH
RUN yum -y install vim                # 给官方原生的centos 增加 vim指令
RUN yum -y install net-tools        # 给官方原生的centos 增加 ifconfig命令
EXPOSE 80                            # 暴露端口号为80
CMD echo $MYPATH                    # 输出下 MYPATH 路径
CMD echo "-----end----"                
CMD /bin/bash                        # 启动后进入 /bin/bash
# 4.通过这个文件构建镜像
# 命令: docker build -f 文件路径 -t 镜像名:[tag] .
$ docker build -f mydockerfile-centos -t mycentos:0.1 .
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mycentos            0.1                 cbf5110a646d        2 minutes ago       311MB
# 6.测试运行
docker run -it mycentos:0.1         # 注意带上版本号,否则每次都回去找最新版latest
pwd    
/usr/local                            # 与Dockerfile文件中 WORKDIR 设置的 MYPATH 一致
vim                                # vim 指令可以使用
ifconfig                             # ifconfig 指令可以使用
# docker history 镜像id 查看镜像构建历史步骤
docker history 镜像id

CMD 和 ENTRYPOINT区别

CMD                    # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT            # 指定这个容器启动的时候要运行的命令,可以追加命令

测试CMD

# 编写dockerfile文件
$ vim dockerfile-test-cmd
FROM centos
CMD ["ls","-a"]                    # 启动后执行 ls -a 命令
# 构建镜像
$ docker build  -f dockerfile-test-cmd -t cmd-test:0.1 .
# 运行镜像
$ docker run cmd-test:0.1        # 由结果可得,运行后就执行了 ls -a 命令
.
..
.dockerenv
bin
dev
etc
home
# 想追加一个命令  -l 成为ls -al:展示列表详细数据
$ docker run cmd-test:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\":
executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled 
# cmd的情况下 -l 替换了CMD["ls","-l"] 而 -l  不是命令所以报错

测试ENTRYPOINT

# 编写dockerfile文件
$ vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建镜像
$ docker build  -f dockerfile-test-entrypoint -t cmd-test:0.1 .
# 运行镜像
$ docker run entrypoint-test:0.1
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found ...
# 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x   1 root root 4096 May 16 06:32 .
drwxr-xr-x   1 root root 4096 May 16 06:32 ..
-rwxr-xr-x   1 root root    0 May 16 06:32 .dockerenv
lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
drwxr-xr-x   5 root root  340 May 16 06:32 dev
drwxr-xr-x   1 root root 4096 May 16 06:32 etc
drwxr-xr-x   2 root root 4096 May 11  2019 home
lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 11  2019 lib64 -> usr/lib64 ....

实战Tomcat镜像

1、准备镜像文件

准备tomcat 和 jdk 到当前目录,编写好README 提前下好放到对应的目录下的

2、编写dokerfile

#如果dockerfile是dockerfile build的时候就不需要输入文件名 默认就是dockerfile
vim dockerfile

FROM centos                                         # 基础镜像centos
MAINTAINER                                          # 作者
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/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test 
-v /home/kuangshen/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、发布项目

(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)

发现:项目部署成功,可以直接访问!

我们以后开发的步骤:需要掌握Dockerfile的编写!我们之后的一切都是使用docker镜像来发布运行!

发布自己的镜像

发布到 Docker Hub

1、地址 https://hub.docker.com/

2、确定这个账号可以登录

3、登录

$ docker login --help
Usage:  docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username
$ docker login -u 你的用户名 -p 你的密码

4、提交 push镜像

# 会发现push不上去,因为如果没有前缀的话默认是push到 官方的library
# 解决方法:
# 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
$ docker build -t kuangshen/mytomcat:0.1 .
# 第二种 使用docker tag #然后再次push
$ docker tag 容器id kuangshen/mytomcat:1.0 #然后再次push
$ docker push kuangshen/mytomcat:1.0

发布到 阿里云镜像服务上

看官网 很详细https://cr.console.aliyun.com/repository/

$ sudo docker login --username=zchengx registry.cn-shenzhen.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]
# 修改id 和 版本
sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:1.0
# 修改版本
$ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]

Docker网络

理解Docker 0

学习之前清空下前面的docker 镜像、容器

# 删除全部容器
$ docker rm -f $(docker ps -aq)
# 删除全部镜像
$ docker rmi -f $(docker images -aq)

# 查看地址 可看见地址的使用情况
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:09:3d:27 brd ff:ff:ff:ff:ff:ff
    inet 172.16.25.125/20 brd 172.16.31.255 scope global dynamic noprefixroute eth0
       valid_lft 299906777sec preferred_lft 299906777sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:5a:5a:30:41 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
59: veth49a5c33@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether de:4d:2c:c0:4a:52 brd ff:ff:ff:ff:ff:ff link-netnsid 0

问题: docker 是如果处理容器网络访问的?(容器跟容器的网络通信)

# 测试  运行一个tomcat
$ docker run -d -P --name tomcat01 tomcat
# 查看容器内部网络地址
$ docker exec -it 容器id ip addr
# 发现容器启动的时候会得到一个 eth0@if91 ip地址,docker分配!
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    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
261: eth0@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以!
$ ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.074 ms

原理

1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!

# 我们发现这个容器带来网卡,都是一对对的
# veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的
# OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术

我们来测试下tomcat01和tomcat02是否可以ping通

可以但是ping 容器名不行的 语法也通不了 ip是可以的

# 创建两个tomcat

# 获取tomcat01的ip 172.17.0.2
$ docker-tomcat docker exec -it tomcat01 ip addr  
550: eth0@if551: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 让tomcat02 ping tomcat01       
$ docker-tomcat docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms
# 结论:容器和容器之间是可以互相ping通 ip是可以ping通的 但是ping 容器名称就不行了

结论:tomcat01和tomcat02公用一个路由器,docker0。

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

小结

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

Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)

只要容器删除,对应的网桥一对就没了!

思考一个场景:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以通过名字来进行访问容器?

–link

docker exec -it tomcat02 ping tomca01   # ping不通 注意上面ping ip是可以的
#结果
ping: tomca01: Name or service not known

# 运行一个tomcat03 --link tomcat02 
docker run -d -P --name tomcat03 --link tomcat02 tomcat
5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef

# 3连接2
# 用tomcat03 ping tomcat02 可以ping通
# 这种命令是不进入docker里面运行一些命令
[root@lisen ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.124 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.071 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.078 ms

# 2连接3
# 用tomcat02 ping tomcat03 ping不通
[root@lisen ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
# 这说明这个link是单向的A --link b a就能ping通b

探究

docker inspect tomcat03 #可查看网络id

docker network inspect 网络id # 网段相同 都一样

"Containers": {
            "da8e64ff0cff7cc5fb972e6378e5bdbe754b650087309287430f3f1da1745189": {
                "Name": "tomcat02",
                "EndpointID": "dce022ed437d228f912436423e806add7dac9431b02d81a5d59417091597988c",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "ed2dde073b32d62424372bc8cc71355873bac3da56bcc89aa0acc2c95a78cb26": {
                "Name": "tomcat01",
                "EndpointID": "3a3a8a52450c1f75c325ed69b5620e28b6d8371e3190f9fae2a4569a43817f7d",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "f0bfe130592b16b9e8abd017eeef2466cc0bfed78cfa3847a8db02c313688fcd": {
                "Name": "tomcat03",
                "EndpointID": "742b907691b7387a51762bc417d7ac8957e0b33b39a283d990e96ae84cf489c1",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            }
        },
        
        
# 可查看links的信息
docker inspect tomcat03
        
"Links": [
        "/tomcat02:/tomcat03/tomcat02"
    ],
    
# docker02 是没有的 单向的

# 查看tomcat03里面的/etc/hosts发现有tomcat02的配置
[root@lisen ~]# docker exec tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 da8e64ff0cff
172.17.0.4	f0bfe130592b

–link 本质就是在hosts配置中添加映射

现在使用Docker已经不建议使用–link了!

自定义网络,不适用docker0!

docker0问题:不支持容器名连接访问!

自定义网络

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网络

[root@lisen ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
06402e764161        bridge              bridge              local
14fe54efd95e        host                host                local
8988d4414cb5        none                null                local

网络模式

  • bridge :桥接 docker(默认,自己创建也是用bridge模式)
  • none :不配置网络,一般不用
  • host :和所主机共享网络
  • 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

# 查看网络的 有刚才自定义的mynet
[root@lisen ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
06402e764161        bridge              bridge              local
14fe54efd95e        host                host                local
74a7c0f53818        mynet               bridge              local
8988d4414cb5        none                null                local
# 查看mynet的信息
[root@lisen ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "74a7c0f53818c5a85a8298d570c8d8e811f27a3410188333c1c02c02d9c78711",
        "Created": "2020-09-03T14:33:31.928887101+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
# 创建两个tomcat容器 用mynet
[root@lisen ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat:9.0.37
[root@lisen ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:9.0.37

# 这是现在mynet的信息 Containers多了两个信息
[root@lisen ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "74a7c0f53818c5a85a8298d570c8d8e811f27a3410188333c1c02c02d9c78711",
        "Created": "2020-09-03T14:33:31.928887101+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "adb7513f0131ea6a0618c39b87254f9fad6306592b2eabceb06346137f40ac5b": {
                "Name": "tomcat-net-02",
                "EndpointID": "63c2cf7f8999cf3e17703f4dfd26ea4eb39ae61341824207ed0cd5fd8d40e181",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "cd335df7ea4ca079d66855ff3156f319c5b9b497d1169ebaca14b06a5274cd88": {
                "Name": "tomcat-net-01",
                "EndpointID": "2cf1de0625c7c60a0b84c1fe0d132afeea260a40fece11ee181a2cd23f94c407",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]


#测试两者之间是否可以互相ping通 是可以的
[root@lisen ~]# docker exec tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.104 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.101 ms

[root@lisen ~]# docker exec tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.075 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.085 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.092 ms

我们自定义的网络docker当我们维护好了对应的关系,推荐我们平时这样使用网络!

好处:就是redis的集群跟mysql的集群是独立的 互相隔离

redis -不同的集群使用不同的网络,保证集群是安全和健康的

mysql -不同的集群使用不同的网络,保证集群是安全和健康的

网络连通

# 如何使用 看docker network下的帮助 有个connect
[root@lisen ~]# docker network --help
Usage:	docker network COMMAND
Manage networks
Commands:
  connect     Connect a container to a network

# 再看connect下的帮助 就知道使用方式了
[root@lisen ~]# docker network connect --help
Usage:	docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
      --alias strings           Add network-scoped alias for the container
      --driver-opt strings      driver options for the network
      --ip string               IPv4 address (e.g., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container


# 测试两个不同的网络连通  再启动两个tomcat 使用默认网络,即docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
# 此时ping不通(上面也证实过)

# 要将tomcat01 连通 tomcat—net-01 ,连通就是将 tomcat01加到 mynet网络
# 一个容器两个ip(tomcat01)

# 将tomcat01加入到mynet的网络中
docker network connect tomcat01 mynet

# 01连通 ,加入后此时,已经可以tomcat01 和 tomcat-01-net ping通了
# 02是依旧不通的

结论:假设要跨网络操作别人,就需要使用docker network connect 连通!

实战:部署Redis集群

分片+高可用+负载均衡(不是哨兵)

# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个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


# 通过脚本运行六个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/sh #redis默认没有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 run -p 6371:6379 -p 16671:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 

#进入redis 客户端 
/data # redis-cli -c

#这就是三主三从
127.0.0.1:6379> cluster nodes
d7ed3e7e0bdbc201a4cf4a9bbea8cf0a7f3c7e55 172.38.0.16:6379@16379 slave 6a05f953fd4957681380f92e35048510b9d37f43 0 1599119396000 6 connected
2e628ddbdf44f8ab4ebfcf0cba5d3f19e89a22aa 172.38.0.13:6379@16379 master - 0 1599119396726 3 connected 10923-16383
6a05f953fd4957681380f92e35048510b9d37f43 172.38.0.12:6379@16379 master - 0 1599119397528 2 connected 5461-10922
2e060c950f68953efc5f15ef822122afad9f96cf 172.38.0.14:6379@16379 slave 2e628ddbdf44f8ab4ebfcf0cba5d3f19e89a22aa 0 1599119397728 4 connected
f2738a5e4db18bf6cca08f2f60792e620f142b83 172.38.0.11:6379@16379 myself,master - 0 1599119395000 1 connected 0-5460
3368b08de6e2514495d6bb355ba8b69459ba5a6c 172.38.0.15:6379@16379 slave f2738a5e4db18bf6cca08f2f60792e620f142b83 0 1599119396000 5 connected

我们使用docker之后,所有的技术都会慢慢变得简单起来!

SpringBoot微服务打包Docker镜像

1、构建SpringBoot项目

2、打包运行
mvn package

3、编写dockerfile

FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]

4、构建镜像

# 1.复制jar和DockerFIle到服务器
# 2.构建镜像
$ docker build -t xxxxx:xx  .

5、发布运行

以后我们使用了Docker之后,给别人交付就是一个镜像即可!