docker文档

一、docker概述

1、java项目通过docker打包成镜像(包含了所有的环境)放到docker仓库中,只需要下载发布的镜像直接运行即可;

2、虚拟机技术的缺点:

资源占用多、冗余步骤多、启动很慢

容器化技术:

比较docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一套硬件,运行一个完整的操作系统,然后在系统上安装和运行软件
  • 容器内的应用直接运行在宿主主机的内容。容器是没有自己的内核的也没有虚拟我们的硬件,所以轻便
  • 每个容器都是相互隔离的,每个容器内核都有一个属于一个自己的而文件系统,互不影响;

在一个物理机上可以运行多个容器实例;

3、docker基本组成

镜像(image):

docker镜像就好比一个模板,可以通过这个模板来创建容器服务,tomcat镜像==》run==》tomcat1(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中)

容器(container):

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

启动,停止,删除,基本命令;

目前可以吧这个容器理解为一个建议的linux系统

仓库(repository):

仓库就是存放镜像的地方;

仓库分为公有仓库和室友仓库;

Docker Hub(默认是国外的)

阿里云...都有对应的容器服务器(配置镜像加速!)

二、docker安装

复制代码
uname -r   
// 查看系统内核  
3.10.0-1127.el7.x86_64
cat /etc/os-release
// 查看系统版本
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装

步骤一:卸载旧的docker版本

复制代码
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

步骤二:需要的安装包

yum -y install gcc

yum -y install gcc-c++

复制代码
yum install -y yum-utils

步骤三:设置镜像的仓库

复制代码
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
    // 默认是国外仓库
    
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    // 国内

#更新yum软件包索引

复制代码
yum makecache fast

步骤四:安装docker相关的docker-ce社区版 ee企业版

复制代码
yum install docker-ce docker-ce-cli containerd.io

步骤五:启动docker

复制代码
systemctl start docker

步骤6:使用docker version是否安装和启动成功

步骤7:hello world

找不到hello-world这和镜像,所以去仓库下载

复制代码
docker run hello-world

步骤8,查看一下下载的hello-world镜像;

卸载docker

复制代码
#卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#删除资源, 下面这个路径是docker的默认路径
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

阿里云镜像加速器配置,需要购买阿里云然后利用对应的加速器地址;

docker整个流程:

三、工作原理

docker是怎么工作的?

docker是一个client-server结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问。

dockerServer接受到docker-client的指令,就会执行这个命令!

docker为什么比vm块?

1、docker拥有着比虚拟机更少的抽象层;

2、docker利用的是宿主机的内核,vm需要的是guest os

新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导性的操作。

虚拟机级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级;

四、docker的常用命令

复制代码
docker version  # 显示docker版本信息
docker info  # 显示docker的系统信息,包括镜像和容器
docker --help  # 查看命令指令
docker 命令 --help  # 查看命令帮助文档
docker ps -aqf "name=容器名字" #根据容器名字查询容器id

镜像命令

复制代码
docker images  # 查看本机主机上的所有镜像
repository 是镜像的仓库源

docker images -a 显示所有镜像
docker images -q 显示所有镜像的id
复制代码
docker search mysql
# 可选项
--filter=STARS=3000  搜索出来的镜像就是STARS大于3000的

docker pull 下载镜像

复制代码
docker pull mysql
等价于 docker pull docker.io/library/mysql:latest

Using default tag: latest
latest: Pulling from library/mysql
a10c77af2613: Pull complete
b76a7eb51ffd: Pull complete
258223f927e4: Pull complete
2d2c75386df9: Pull complete
63e92e4046c9: Pull complete
f5845c731544: Pull complete
bd0401123a9b: Pull complete
3ef07ec35f1a: Pull complete
c93a31315089: Pull complete
3349ed800d44: Pull complete
6d01857ca4c1: Pull complete
4cc13890eda8: Pull complete
Digest: sha256:aeecae58035f3868bf4f00e5fc623630d8b438db9d05f4d8c6538deb14d4c31b
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest

删除命令

复制代码
docker rmi -f  容器id   # 删除指定的容器
docker rmi -f 容器id 容器id  # 删除多个容器
docker rmi -f  $(docker images -aq)  #删除全部的镜容器

容量命令

有了镜像才可以创建容器,下载一个centos镜像来测试

复制代码
docker pull centos

新建容器并启动

复制代码
docker run [可选参数] image
#参数说明
--name="Name"  容器名字tomcat01,tomcat02 用来区分容器
-d 后台运行
-it  使用交互式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
   -p 主机端口:容器端口 (常用)
   -p 容器端口

# 启动并进入容器 ,此容器实际上就是一个系统容器
docker run -it centos /bin/bash
# 从容器中退回主机
exit  

# 在dockerfile中这样可以让容器内的8080端口开放
EXPOSE 8080 

#该EXPOSE指令通知Docker容器在运行时监听指定的网络端口。EXPOSE不会使主机可以访问容器的端口。为此,您必须使用该-p标志来发布一系列端口,或者使用该-P标志来发布所有公开的端口。您可以公开一个端口号,然后将其发布到另一个端口号的外部。
docker run -p 8765:8080  image_id
#这样就将容器内部的8080映射到宿主机的8765端口

列出所有运行的容器

复制代码
docker ps   列出正在运行的容器
docker ps -a 列出当前正在运行的容器包括历史运行的容器的信息
docker ps -n=? 显示最近创建的容器  ?是个数
docker ps -aq  显示容器的编号

退出容器

复制代码
exit #直接退出容器并且停止
ctrl +p+q  # 容器不停止退出

删除容器

复制代码
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 #强制停止当前容器

其他常见命令

后台启动命令
复制代码
后台运行
docker run -d centos
# 如果docker发现容器中没有应用会自动停止
# nginx容器启动后,如果没有服务,也会停止,除非有对应的正常运行的进程
#tomcat就不会。
日志命令
复制代码
docker logs --help
docker logs -f -t --tail ? 容器id  #?是输出日志的数量

后台运行并启动一个shell脚本
docker run -d centos /bin/sh -c "while true;do echo chwchw;sleep 1;done"

#显示日志
docker logs -tf --tail 10 b1c950bcae92  显示指定行数的日志
docker logs -tf b1c950bcae92  显示所有的日志
查看容器中进程信息
复制代码
docker top 容器id

uid 用户id , PID父进程id PPID当前进程id

复制代码
docker inspect 容器id  # 查看容器的详细信息

[
    {
        "Id": "b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366",
        "Created": "2021-11-22T03:29:21.430035131Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo chwchw;sleep 1;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 121458,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-11-22T03:29:21.893497652Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366/hostname",
        "HostsPath": "/var/lib/docker/containers/b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366/hosts",
        "LogPath": "/var/lib/docker/containers/b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366/b1c950bcae92fe15b193f542bf93f6fd6633f2254e78797b60dc7692af023366-json.log",
        "Name": "/amazing_hugle",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/b46cf017e1965e464b3181f1440ac04055b2b21ef3d32d076e5b23435da61a2b-init/diff:/var/lib/docker/overlay2/6794a6fac22d33ea25863302158aa0a887204f841c44c0662020cf5a3316c35b/diff",
                "MergedDir": "/var/lib/docker/overlay2/b46cf017e1965e464b3181f1440ac04055b2b21ef3d32d076e5b23435da61a2b/merged",
                "UpperDir": "/var/lib/docker/overlay2/b46cf017e1965e464b3181f1440ac04055b2b21ef3d32d076e5b23435da61a2b/diff",
                "WorkDir": "/var/lib/docker/overlay2/b46cf017e1965e464b3181f1440ac04055b2b21ef3d32d076e5b23435da61a2b/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "b1c950bcae92",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true;do echo chwchw;sleep 1;done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "066cd022d6d9ba0d3f8bc970242e902799b21fa2014eeb21b6f777d4c75bc604",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/066cd022d6d9",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "28d4949fa1c350b83ff1b01efea00f78461603218d4e6030fe2c9c02f8d3a10b",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "780073ba90ed793ad3ff95d9b89d360ec490237fd3a2e283e517fad795e5e827",
                    "EndpointID": "28d4949fa1c350b83ff1b01efea00f78461603218d4e6030fe2c9c02f8d3a10b",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
进入当前正在运行的容器
复制代码
docker exec -it 容器id bashShell   #进入容器开启一个新的终端,可以在里面操作(常用)
docker attach 容器id  # 进入容器当前容器正在运行进程
将容器内的东西赋值到宿主主机上
复制代码
[root@localhost docker_test]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
fbb63cc34c61   centos    "/bin/bash"   2 minutes ago   Up 2 minutes             modest_bouman
[root@localhost docker_test]# docker attach fbb63cc34c61
[root@fbb63cc34c61 /]# ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@fbb63cc34c61 /]# cd home
[root@fbb63cc34c61 home]# ls
[root@fbb63cc34c61 home]# touch test.java
[root@fbb63cc34c61 home]# ls
test.java
[root@fbb63cc34c61 home]# exit
[root@localhost docker_test]# docker cp fbb63cc34c61:/home/test.java ./
[root@localhost docker_test]# ls
chw.java  test.java

拷贝只是一个手动的过程,后面可以使用-v 卷技术,实现自动

五、docker安装Nginx

复制代码
#1、搜索镜像 search
#2、下发镜像 pull
#3、启动镜像 docker run -d --name nginx01 -p 3344:80 nginx
# 将容器中80端口映射到宿主主机的3344端口
-d 表示后台进行
--name 容器命名
-p 宿主主机端口:容器内部端口

在宿主机访问:

复制代码
[root@localhost docker]# docker exec -it nginx01 /bin/bash
root@077e7ee41262:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@077e7ee41262:/# cd /etc/nginx/
root@077e7ee41262:/etc/nginx# ls
conf.d  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  uwsgi_params

六、docker部署tomcat

复制代码
#下载tomcat镜像并启动为容器 , --rm 代表在使用结束后会把对应的容器删除掉
docker run -it --rm tomcat:9.0

#启动tomcat对应版本的容器
docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0
#进入容器观察
docker exec -it tomcat01 /bin/bash

docker exec -it tomcat01 /bin/bash

七、部署es+kibana

复制代码
es暴露的端口很多
es 十分消耗内存
es的数据一般需要放置到安全的目录
#下载并启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

启动后很卡可以做内存限制,但是好像启动不起来
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e  "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Mmx512m"  elasticsearch:7.6.2

#确定后访问一下
[root@localhost docker]# curl localhost:9200
{
  "name" : "8aa24f9679b3",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "GLq04zGNQAycdGMv4tns1A",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

使用kibana连接es

可视化

portainer

shell 复制代码
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

八、docker镜像

1、镜像是什么:

镜像是一种轻量级,可以执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的的所有的内容,包括代码运行时库,环境变量和配置文件。所有的应用直接打包成docker镜像就可以run起来。

镜像获取:

  • 从远程仓库下载
  • 拷贝
  • 自己制作dockerFile创建镜像

2、镜像加载原理

UnionFs 联合文件系统

下载的时候看到的是一层一层的这个

UnionFS:Union文件系统是一种分层的、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础,镜像可以通过分层进行集成,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同事加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层的文件系统叠加起来,这样最终的文件系统会包含所有的底层的文件和目录。

docker加载镜像的原理

docker的镜像实际上由一层一层呢个的文件系统组成,这种层级的文件系统叫UnionFs

bootfs (boot file system) 主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动的时候回加载bootfs文件系统,在docker镜像的底层是bootfs,这一层与我们典型的Linux、unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(roof file system)在bootfs之上,包含的就是典型的linux系统中的/dev,/proc,/bin,/eyc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubuntu、Centos等。

平时安装的centos都是好几个g的,cocker才几百m?

对于一个精简的os,rootfs可以很小,只包含基本的命令、工具和程序库就可以了,因为底层直接用Host的kenel,(也就是直接用主机的内核),自己只需要提供rootfs就可以了,由此可见对于不同的linux发行版,bootfs基本是一直的,rootfs有点差别,因此不同的发版版可以共用bootfs(因为底层的引导都是一样的),由此就减少了很大的存储开销。

虚拟机的启动时分钟级别的,而容器是秒级的,就是因为此。

3、分层理解

比如这,每一步的安装就是一个层。

docker镜像都是只读的,当启动容器的时候,一个新的可写层会被加载到镜像的顶部,这一层就是我们常说的容器层,容器之下叫镜像层。所有的容器都是基于容器层的。

九、commit镜像

shell 复制代码
docker commit 提交容器成为一个新的副本
#命令和git类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

实战测试

复制代码
#启动一个默认的tomcat
#发现这个默认的tomcat是没有webapps应用的,官方的镜像下默认是没有的
#拷贝应用到webapp后相当于加了一个容器层
#可以将我们操作过的镜像提交后成为一个镜像,后续就可以直接使用,commit为镜像后又成为了一个整体的镜像层。

如果想要保存当前容器的状态,就可以通过commit来提交获得一个镜像,这优点类似虚拟机的快照。

十、容器数据卷

容器的持久化和同步操作!容器键也可以数据共享。

使用容器数据卷

shell 复制代码
docker run -it -v 主机目录:容器内目录 镜像名字:镜像tag
docker inspect 容器id  查看容器的详细信息
#通过inspect可以查看是否挂载成功,如下图:

实践:安装musql,解决mysql的数据持久化问题

复制代码
docker pull mysql:5.7  拉去镜像
docker run -d -p 3301:3306 \
-v /home/chw/doc/mysql/conf:/etc/mysql/conf.d \
-v /home/chw/doc/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# -p 端口映射
# -e 环境配置,配置数据库密码
# -d 后台运行
# -v 卷挂载

可以用数据库连接工具测试一下连接数据库用3301端口,在虚拟机上外部系统可以访问,外部系统和虚拟机上通了网络之后就可以。

删除掉mysql的容器,宿主机上挂载出来的mysql的数据文件不会被删除。

具名和匿名挂载

匿名挂载

复制代码
#匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /ect/nginx/ nginx
# -P 大写的P是随机指定端口
# 不指定宿主机的目录,直接挂载容器内的路径

#查看所有的容器卷
docker volume ls 

#如下这种没有具体的容器名字的就是匿名挂载的
复制代码
#具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx

#查看挂载的目录的详细信息
docker volume inspect juming-nginx

进入docker的工作目录,没有直接挂载的主机具体路径的容器内部挂载的东西在docker工作目录下的volumes中。

所有的docker容器内的卷,在没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data 中

我们通过具体挂载可以方便我们找到一个卷,大多数情况下是使用具名挂载。

复制代码
-v 容器内路径  #匿名挂载
-v 卷名字:容器内路径 #具名挂载
-v 宿主机路径:容器内路径 #指定路径挂载

拓展

复制代码
#通过 -v 容器内路径:ro rw 改变读写权限
ro  readonly  只读
rw  readwrite 可读可写
#一旦设定了ro只能通过宿主机来改变,容器内是无法操作的 ,rw则容器和宿主机都可以改变
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx

十一、DockerFile

dockefile中卷挂载

数据卷之dockerfile

commit可以构建一个镜像,dockerFile也可以,其实就是一堆命令脚本

镜像是一层一层的,dockerfile中一个命令就是一层。

dockerfile内容如下:

复制代码
#文件中的内容,指令大写
#VOLUME给你新建了两个匿名卷 , 你run了该对象的容器后 再去进入容器看根目录 , 就能看到这两个匿名卷文件夹

FROM centos

VOLUME ["volume01","volume02"]
CMD echo "---end----"
CMD /bin/bash

docker build -f dockerfile1 -t chw/centos:1.0 .
#-f 指定file的地址   -t 生成目标镜像名字, 后面的.是指生成在当前目录
#给镜像命名的是偶不能用/开头
docker build --help 可以查看帮助文档

如下两个volume01 02 目录就是dockerfile构建镜像的时候自动挂载的。这个卷和外部一定有一个同步的目录,这个只写了容器内的目录,是一个匿名挂载。

在容器内的volume01构建一个文件,查看一下宿主机上的随机挂载目录是否同步到了,如下是看到成功同步

如果构建镜像的dockerfile中没有挂载卷,那么就启动的时候手动-v进行挂载

数据卷容器

目的:容器跟容器之间同步!

多个mysql同步数据

复制代码
#启动三个容器
docker run -it --name docker01 docker01 chw/centos:1.0
docker run -it --name docker02 --volumes-from docker01 chw/centos:1.0
# 在docker02启动的时候同步挂载docker01容器内的数据卷,在docker01的volume01数据卷中创建一个文件,在docker02中时会同步到的。同理在docker02创建在dcoker01中也是有的。

docker run -it --name docker03 --volumes-from docker01 chw/centos:1.0

docker01 就叫数据卷容器

通过--volumnes-from 就可以实现容器间的数据卷共享。就算吧docker01这个容器给删除掉,其他的容器中的数据还是存在的。

redis数据共享或者数据库数据共享。

多个mysql实现数据共享

复制代码
docker run -d -p 3301:3306 \
-v /home/chw/doc/mysql/conf:/etc/mysql/conf.d \
-v /home/chw/doc/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3301:3306 \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3301:3306 \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql01 \
volumes-from mysql01 mysql:5.7
#这个时候实现两个容器数据同步

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

但是一旦通过-v持久化到本地,本地的数据是不会删除的。

dockerfile介绍

参数命令脚本。

构建步骤:

1、编写dockerfile文件

2、docker build构建成为一个镜像

3、docker run 运行镜像

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

进入官网随便找个镜像点击进去描述,点击描述会跳转到对应的github地址,上面就是对应的dockerfile文件。

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

DockerFIle构建过程

基础知识:

1、每个保留关键字(指令)必须是大写字母

2、执行从上到下顺序执行

3、#表示注释

4、每一个指令都会创建提交一个新的镜像层

dockerfile是面向开发的,发布项目,做镜像,就需要编写dockefile文件。

dockerFIle:构建文件,定定义了一切的步骤,源代码

dockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品,原来是jar、war。

Docker容器:容器就是镜像运行起来提供服务的。

dockerFile指令

前面部分就是使用别人的镜像,然后通过制定下面的一些参数进行启动,这类东西可以直接写在dockerfile中然后构建一个完成的镜像。

复制代码
FROM  #基础镜像,一切从这里开始构建 centos ubuntu
MAINTAINER  #镜像是谁写的 姓名+邮箱。
RUN # 镜像构建的时候需要运行的命令
ADD #步骤,tomcat镜像,加个tomcat的压缩包,添加内容
WORKDIR #镜像的工作目录
VOLUME # 设置容器卷,挂载的目录
EXPOSE #指定暴露端口  不再这里暴露的话就需要在启动的话通过-p进行暴露
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,而且可被替代
#ls -l   然后在docker run的时候追加命令 ls -a 这样被将-l替换掉
#而下面的那种方式的话则是命令追加。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令。可以追加命令。
ONBUILD #当构建一个被继承的dockerfile这个时候就会运行ONBUILD指令,触发指令
COPY #类似ADD,将我们的文件拷贝到镜像中。
ENV  #构建的时候设置环境变量

创建一个自定义的centos

复制代码
FORM centos
MAINTAINER chw<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

创建一个dockerfile2

复制代码
docker build -f dockerfile2 -t mycentos:0.1 .  #构建镜像

直接进入我们设置的目录

可以列出本地的镜像变更历史

使用docker history 镜像id

查看镜像的具体生成过程

CMD和ENTRYPOINT的区别

复制代码
dockerfile3:
FROM centos
CMD ["ls","-a"]
如下图,返现ls -a 命令生效了

执行如下命令是行不通的,不能直接在cmd后面追加-l,所以报错

docker run cmdtest ls -al 写一个完全的路径才可以,以为-l会直接替换掉原来的命令

复制代码
FROM centos
ENTRYPOINT ["ls","-a"]
#使用entrypoiny
#构建完镜像后启动如下在启动的时候加上-l 是会直接加载["ls","-a"] 后面的,直接执行,不会报错

构建tomcat镜像

1、准备tomcat、jdk压缩包

2、写dockerfile

shell 复制代码
FROM centos
MAINTAINER chw<[email protected]>
COPY readme.txt /usr/local/readme.txt

ADD jdk-8u261-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.56.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME=/usr/local/jdk1.8.0_261
ENV CLASSPATH=$JAVA_HOME/lib/dt.jar;$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME=/usr/local/apache-tomcat-9.0.56
ENV CATALINA_BASH=/usr/local/apache-tomcat-9.0.56
ENV PATH=$PATH:$JAVA_HOME/bin;$CATALINA_HOME/lib;$CATALINA_HOME/bin
EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.56/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.56/logs/catalina.out

3、构建镜像

4、启动镜像

shell 复制代码
docker run -d -p 9090:8080 --name chw_tomcat -v /home/chw/doc/tomcat/test:/usr/local/apache-tomcat-9.0.56/webapps/test -v /home/chw/doc/tomcat/logs/:/usr/local/apache-tomcat-9.0.56/logs diytomcat
#启动镜像

5、访问测试

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

web.xml放在WEB-INF下

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
  <web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

</web-app>

写个jsp测试

jsp 复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>chw tomcat</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("my test logs---");
%>
</body>
</html>

发布自己镜像到dockerhub

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

2、确定账号可以登录

3、在服务器上提交自己的镜像

shell 复制代码
#登录
docker login -u hikechw

4、登录完了之后提交镜像

复制代码
docker tag 镜像id 镜像名字:tag   #给镜像改个名字
docker push xxx:tag

发布到阿里云

1、登录阿里云

2、容器镜像服务

复制代码
docker logout  #登出之前的服务
docker login --username=xxx 镜像仓库地址

docker小结

复制代码
docker load xxx.tar
docker load --input xxx.tar
# 加载压缩包进行
docker save -o xxx.tar
#保存镜像到本地
复制代码
#移除所有历史容器
docker rm -f $(docker ps -aq)

十二、Docker网络

理解docker0

三个网卡,如果没有阿里云的话正常就是有本地会还地址和docker0地址。

docker容器中网络如何打通

复制代码
#启动一个tomcat容器,随便暴露端口
[root@localhost doc]# docker run -d -P --name tomcat01 tomcat

#查看容器内部的ip地址 
docker exec -it tomcat01 ip addr
# 如果容器没有ip addr命令那么通过/bin/bash直接进入docker容器,然后执行安装命令即可
apt update  # 更新安装工具
apt install -y iproute2  # 安装ipaddr命令
复制代码
#linux能不能ping同容器内部,是可以直接在宿主机ping同容器内部的ip的

原理

1、我们每安装一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个docker0网卡,桥接模式,使用的技术是evth-pair技术!

再次测试ipaddr,启动容器后发现多了个veth 190,

2、再启动一个容器尝试,发现又多了一个网卡,而且是成对出现的193对应着192,上面191对应着190

复制代码
docker run -d -P --name tomcat02 tomcat

我们发现这些容器带来的网卡都是一对一对出现的

evth-pair就是一对虚拟设备接口,成对出现,一段连着的协议,可以彼此相连

正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备。

OpenStak,Docker容器之间的连接,OVS连接,都是使用evth-pair技术。

3、在tomcat02内部直接ping tomcat01的ip网络也是可以的。

复制代码
apt-get install iputils-ping  # 下载安装ping命令

docker exec -it tomcat02 ping 172.17.0.2
# 容器和容器之间的网络是可以直接ping通的

整体的网络通信结构如下:docker0网卡就类似一个路由器,tomcat01和tomcat02都是公用一个路由器docker0,所有的容器不指定网络的情况下都是docker0路由的。docker会给我们的容器分配一个默认的ip。

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

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

场景思考

每次启动容器可能ip不一定,那如果在微服务中配置ip是固定的,该如何处理。

复制代码
docker run -d -P --name tomcat03 --link tomcat02  tomcat
#直接通过服务名将网络连接起来
#这样就可以直接在tomcat03中ping通tomcat02
#实际上这样就是tomcat03中的/etc/hosts文件中做了tomcat02的ip映射,所以可以在tomcat03中直接通过服务名映射到tomcat02
#现在不台建议docker link 做网络连接 
#docker0不支持容器名连接,即不支持自定义网络

自定义网络

复制代码
列出所有的docker

网络模式:

bridge:桥接 docker(默认)

none:不配置网络

host:和宿主机共享网络

container:容器网络连通(局限性大用得少)

复制代码
#我们直接启动命令 --net bridge,而这个就是我们的docker0,不写也是默认
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0的特点,默认,域名不能访问

#自定义一个网络
# --driver bridge
# --subnet 子网地址 /16, 代表有8位可以存放主机地址
# --gateway 网关地址
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet


[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
0bf2e25aa403   bridge    bridge    local
fd6e46734134   host      host      local
6388ad6da0f8   mynet     bridge    local
e87d38772d89   none      null      local
复制代码
docker run -d -P --name tomcat-net-01 --net mynet tomcat
#如果容器没有ping命令的话,需要更新一下apt,再通过apt-get进行install iputils-ping

我们自定义的网络docker都已经帮我们维护好了对应的关系。

网络连通

复制代码
#打通tomcat01到 -mynet
docker network connect mynet tomcat01
#连通之后就是把tomcat01放到了mynet网络下
#一个容器两个ip,一个是公网ip,一个是私网ip
#那么就可以在tomcat-net-02 或者01中ping通tomcat01

tomcat01是连接在docker0上的,如果要连接到mynet的tomcat-net-01,需要将自定义网络mynet连接到tomcat01服务器即可, docker network connect mynet tomcat01

实战:部署redis集群

复制代码
#创建redis网卡
docker network create redis --subnet 172.38.0.0/16

#循环创建配置文件集群
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

docker run -p 6371:6379 -p 16371: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服务并使用redis-server执行配合文件

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

docker exec -it redis-1 /bin/sh  #进入一台redis容器

进入redis容器内部后构建redis集群
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
#使用下面的命令进入集群
redis-cli -c
cluster info 查看信息
cluster nodes 查看所有节点,主机和从机

上面我们把b保存在变量a中,a的保存是由主节点redis-3操作的

如下,我们可以先docker stop redis-3,再进入redis集群get a查看是否存在,需要退出redis集群再进入,可以看到redis-3节点是挂掉了,但是会有其他节点会代替ta成为主节点,返回给我们保存的信息。

构建springboot镜像

Dockerfile

复制代码
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]
EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

#将jar包和dockerfile保存到同一个目录,然后执行build
docker build -t chw-demo .
#随机端口启动,启动后的端口映射可以在docker ps中看到
docker run -d -P  --name chw-web  chw-demo

执行curl localhost:port/test 查看测试返回是否成功

Doker Compose

Docker Swarm (k)

CI/CD之jenkins

相关推荐
木头左5 分钟前
Docker 容器化基础:镜像、容器与仓库的本质解析
docker·容器·eureka
꧁༺朝花夕逝༻꧂6 分钟前
docker详细操作--未完待续
linux·nginx·docker·shell
不穿铠甲的穿山甲8 分钟前
docker 部署redis集群 配置
redis·docker·容器
藥瓿亭25 分钟前
K8S认证|CKS题库+答案| 8. 沙箱运行容器 gVisor
linux·运维·docker·云原生·容器·kubernetes·cks
rocksun29 分钟前
需要尽早知道的容器安全知识
安全·容器·kubernetes
网硕互联的小客服1 小时前
如何排查 Docker 容器资源占用过高的问题?
运维·服务器·网络·安全·docker·容器
ReadThroughLife3 小时前
【已解决】MACOS M4 芯片使用 Docker Desktop 工具安装 MICROSOFT SQL SERVER
microsoft·macos·docker·容器
KrityCat3 小时前
阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】
阿里云·docker·容器
{⌐■_■}3 小时前
【ubuntu】虚拟机安装配置,sh脚本自动化,包含 apt+时间同步+docker+mysql+redis+pgsql
ubuntu·docker·自动化
藥瓿亭11 小时前
K8S认证|CKS题库+答案| 9. 网络策略 NetworkPolicy
linux·运维·docker·云原生·容器·kubernetes·cks