docker

143 阅读19分钟

本文以参与[新人创作礼]活动,一起开启掘金创作之路

镜像基础命1令

pull

下载镜像的命令。镜像从远程镜像仓库服务的仓库中下载。默认情况下,镜像会从 Docker Hub 的 仓库中拉取。
通过下载过程,可以看到,一个镜像一般是由多个层组成,类似 f7e2b70d04ae 这样的串表示层的 唯一 ID。

docker pull tomcat:9.0.20-jre8-alpine

image

通过使用如下两个命令,列出本机已有的镜像

docker images
docker image ls

save

保存一个镜像包

docker save tomcat:9.0.20-jre8-alpine -o tomcat9.tar
docker save tomcat:9.0.20-jre8-slim > tomcat9.slim.tar

load

加载一个镜像包

docker load -i linux.tar
docker load < tomcat9.0.20.tar

search

不推荐使用search命令查找镜像,不够直观。

docker search tomcat

inspect

通过 docker inspect 命令,我们可以获取镜像的详细信息,其中,包括创建者,各层的数字摘要 等。
docker inspect 返回的是 JSON格式的信息,如果您想获取其中指定的一项内容,可以通过 -f 来指 定,如获取镜像大小

docker inspect tomcat:9.0.20-jre8-alpine
docker inspect -f {{".Size"}} tomcat:9.0.20-jre8-alpine

history

一个镜像是由多个层组成的, 通过 docker history命令,可以列出各个层的创建信息,例如:查看 tomcat:9.0.20-jre8-alpine的各层 信息

docker history tomcat:9.0.20-jre8-alpine

tag

标记本地镜像,将其归入某一仓库

docker tag tomcat:9.0.20-jre8-alpine lagou/tomcat:9

rmi

通过如下两个都可以删除镜像

docker rmi tomcat:9.0.20-jre8-alpine
docker image rm tomcat:9.0.20-jre8-alp

容器基础命令

运行容器

docker run -it --rm -p 8080:8080 tomcat:9.0.20-jre8-alpine

容器日志

docker run -itd --name tomcat9 -p 8080:8080 tomcat:9.0.20-jre8-alpine
docker logs -f tomcat9

删除容器

docker rm [OPTIONS] CONTAINER [CONTAINER...]

查看容器列表

docker ps [OPTIONS]

创建容器

创建一个容器但是不启动

docker create -it --name tomcat9 -p 8080:8080 9.0.20-jre8-alpine

启动、重启、终止

docker start tomcat9
docker stop tomcat9
docker restart tomcat9

进入容器

docker exec -it tomcat9.1 /bin/bash docker exec -it tomcat9.1 /sh

查看容器

docker inspect tomcat9

杀掉容器

docker kill tomcat9

网络

自建网络

docker安装后会自动创建3种网络: bridge host none

docker network ls

docker网络理论部分

docker使用Linux桥接网卡,在宿主机虚拟一个docker容器网桥(docker0),docker启动一个容器时会根 据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时docker网桥是每个容器的默认网 关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接 通信。 docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着 外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容 器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时 候就通过[宿主机IP]:[容器端口]访问容器。

docker info

image.png

网络模式

image.png

bridge模式

默认的网络模式。bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容 器通过宿主机的NAT规则后可以访问外网。

Bridge 桥接模式的实现步骤主要如下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和veth1。而veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。

  • Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0网桥上。保证宿主机的网络报文可以发往 veth0;

  • Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为eth0。如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到DockerContainer网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。

Bridge桥接模式的缺陷:

  1. 最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。
  2. 虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。
  3. 另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率.

注意:

veth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的veth(通常命名 为veth),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据 通信

host模式

相当于Vmware中的NAT模式,与宿主机在同一个网络中,但没有独立IP地址。

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是 和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿 主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机 的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就 不能再用了,网络的隔离性不好。

host网络模式需要在容器创建时指定–network=host

host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机 的 IP地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有IP。同时容器内 服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。 host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离 性。

Host 网络模式的缺陷:

最明显的是 Docker Container 网络环境隔离性的弱化。即容器不再拥有隔离、独立的网络环境。

另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使 用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;

另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有 部分端口已经用以 bridge 网络模式容器的端口映射。

Container网络模式

一种特殊host 网络模式

Container 网络模式是 Docker 中一种较为特别的网络的模式。在容器创建时使用– network=container:vm1指定。(vm1指定的是运行的容器名)

处于这个模式下的 Docker 容器会共享一个网络环境,这样两个容器之间可以使用localhost高效快速通 信。

缺陷:它并没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他 设备)。

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共 享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信

none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网 络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网 卡、配置IP等。

这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过-- network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性

overlay 网络模式

Overlay 网络,也称为覆盖网络。主要用于docker集群部署。

Overlay 网络的实现方式和方案有多种。Docker自身集成了一种,基于VXLAN隧道技术实现。

Overlay 网络主要用于实现跨主机容器之间的通信。

应用场景:需要管理成百上千个跨主机的容器集群的网络时

macvlan 网络模式

macvlan网络模式,最主要的特征就是他们的通信会直接基于mac地址进行转发。

这时宿主机其实充当一个二层交换机。Docker会维护着一个MAC地址表,当宿主机网络收到一个数据包 后,直接根据mac地址找到对应的容器,再把数据交给对应的容器。

容器之间可以直接通过IP互通,通过宿主机上内建的虚拟网络设备(创建macvlan网络时自动创建), 但与主机无法直接利用IP互通。

应用场景:由于每个外来的数据包的目的mac地址就是容器的mac地址,这时每个容器对于外面网络来 说就相当于一个真实的物理网络设备。因此当需要让容器来的网络看起来是一个真实的物理机时,使用 macvlan模式

Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点。Linux实现非常轻量级,因为与传统的 Linux Bridge隔离相比,它们只是简单地与一个Linux以太网接口或子接口相关联,以实现网络之间的分 离和与物理网络的连接。

Macvlan提供了许多独特的功能,并有充足的空间进一步创新与各种模式。这些方法的两个高级优点是 绕过Linux网桥的正面性能以及移动部件少的简单性。删除传统上驻留在Docker主机NIC和容器接口之间 的网桥留下了一个非常简单的设置,包括容器接口,直接连接到Docker主机接口。由于在这些情况下没 有端口映射,因此可以轻松访问外部服务。

Macvlan Bridge模式每个容器都有唯一的MAC地址,用于跟踪Docker主机的MAC到端口映射。 Macvlan驱动程序网络连接到父Docker主机接口。示例是物理接口,例如eth0,用于802.1q VLAN标记 的子接口eth0.10(.10代表VLAN 10)或甚至绑定的主机适配器,将两个以太网接口捆绑为单个逻辑接 口。 指定的网关由网络基础设施提供的主机外部。 每个Macvlan Bridge模式的Docker网络彼此隔离, 一次只能有一个网络连接到父节点。

每个主机适配器有一个理论限制,每个主机适配器可以连接一个Docker网络。 同一子网内的任何容器都 可以与没有网关的同一网络中的任何其他容器进行通信macvlan bridge。 相同的docker network命令 适用于vlan驱动程序。 在Macvlan模式下,在两个网络/子网之间没有外部进程路由的情况下,单独网络 上的容器无法互相访问。这也适用于同一码头网络内的多个子网。

bridge网络

image.png

bridge网络表现形式就是docker0这个网络接口。容器默认都是通过 docker0这个接口进行通信。也可以通过docker0去和本机的以太网接口连接,这样容器内部才能访问互 联网

Docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口/网卡,也就是veth pair,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 vetha596da4;
  • 容器一端放到新容器中,并修改名字作为 eth0,这个网卡/接口只在容器的名字空间可见;
  • 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 vetha596da4。

完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 如果不指定--network,创建的容器默认都会挂到 docker0 上,使用本地主机上 docker0 接口的 IP 作为 所有容器的默认网关。

image.png

创建bridge网络

当有两个容器需要通讯时,需要知道相互之间的ip地址,但是当容器重启时ip地址会发生变化,为了解决此问题docker中可以使用--link来完成两个容器的关联,但是这个参数有一定的安全问题,所以不仅已使用

我们可以创建一个bridge网络来解决此问题

docker network create -d bridge mybridge

image.png

新建容器将其的网络与自定义网络绑定

docker run -itd --name nginx --network mybridge nginx:1.19.3-alpine

把一个运行中容器连接到mybridge网络

docker network connect mybridge nginx2
docker network inspect mybridge

none网络

注意,容器使用none模式,是没有物理地址和IP地址。我们可以进入到nginx1容器里,执行ip a命令看 看。只有一个lo接口,没有其他网络接口,没有IP。也就是说,使用none模式,这个容器是不能被其他 容器访问。这种使用场景很少,只有项目安全性很高的功能才能使用到。例如:密码加密算法容器

host网络

容器使用了host模式,说明容器和外层linux主机共享一套网络接口。VMware公司的虚 拟机管理软件,其中网络设置,也有host这个模式,作用也是一样,虚拟机里面使用网络和你自己外层 机器是一模一样的。这种容器和本机使用共享一套网络接口,缺点还是很明显的,例如我们知道web服 务器一般端口是80,共享了一套网络接口,那么你这台机器上只能启动一个nginx端口为80的服务器 了。否则,出现端口被占用的情况。

固定ip地址

docker network create -d bridge --subnet=172.172.0.0/24 --gateway 172.172.0.1 mynetwork

172.172.0.0/24: 24代表子码掩码是255.255.255.0
172.172.0.0/16: 16 代表子码掩码

docker network ls

docker run -itd --name nginx3 -p 80:80 --network mynetwork --ip 172.172.0.10 nginx:1.19.3-alpine

--net mynetwork:选择存在的网络
--ip 172.172.0.10:给nginx分配固定的IP地址

数据

容器中的管理数据主要有两种方式:

  • 数据卷:Data Volumes 容器内数据直接映射到本地主机环境
  • 数据卷容器:Data Volume Containers 使用特定容器维护数据卷

cp命令

当然还有最原始的copy方式,这个也是管理数据的方式,但是基本不会用到。 docker cp :用于容器与主机之间的数据拷贝

宿主机文件复制到容器内
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
容器内文件复制到宿主机
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_

基础镜像

docker pull nginx:1.19.3-alpine

宿主机文件 copy to 容器内

宿主机的index.html页面覆盖容器内的index.html页面

docker run -itd --name nginx -p 80:80 nginx:1.19.3-alpine
cd /data
echo "laosiji" > /data/index.html
docker cp /data/index.html nginx:/usr/share/nginx/html/index.html

数据卷

数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录,它将主机操作系统目录直接映射进 容器。

docker run -v /宿主机绝对路径目录:/容器内目录 镜像名

docker volume ls
docker volume inspect 卷名

数据卷容器

image.png

基础镜像

docker pull centos:7.8.2003
docker pull nginx:1.19.3-alpine
docker pull mysql:5.7.31

run命令

docker run

  • --volumes-from:

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器 也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。

发现创建好的数据卷容器是处于停止运行的状态,因为使用 —volumes-from 参数所挂载数据卷的容器 自己并不需要保持在运行状态。

docker run -d --name data-volume -v /data/nginx:/usr/share/nginx/html -v
/data/mysql:/var/lib/mysql centos:7.8.2003

docker run -itd --name nginx01 -p 80:80 --volumes-from data-volume nginx:1.19.3-
alpine

echo "lagouedu nginx" > /data/nginx/index.html

http://192.168.198.100

docker run -itd --name nginx02 -p 81:80 --volumes-from data-volume nginx:1.19.3-
alpine

http://192.168.198.100:81

docker run -itd --name mysql01 --restart always --privileged=true -p 3306:3306
-e MYSQL_ROOT_PASSWORD=admin --volumes-from data-volume mysql:5.7.31 --
character-set-server=utf8 --collation-server=utf8_general_ci

docker run -itd --name mysql02 --restart always --privileged=true -p 3307:3306
-e MYSQL_ROOT_PASSWORD=admin --volumes-from data-volume mysql:5.7.31 --
character-set-server=utf8 --collation-server=utf8_general_ci

docker-compose

yml配置文件及常用指令

Docker Compose 使用 YAML 文件来定义多服务的应用。YAML 是 JSON 的一个子集,因此也可以使用 JSON。

Docker Compose 默认使用文件名 docker-compose.yml。当然,也可以使用 -f 参数指定具体文件。

Docker Compose 的 YAML 文件包含 4 个一级 key:version、services、networks、volumes

  • version 是必须指定的,而且总是位于文件的第一行。它定义了 Compose 文件格式(主要是API)的版本。注意,version 并非定义 Docker Compose 或 Docker 引擎的版本号。
  • services 用于定义不同的应用服务。上边的例子定义了两个服务:一个名为 lagou-mysql数据库服务以及一个名为lagou-eureka的微服。Docker Compose 会将每个服务部署在各自的容器中。
  • networks 用于指引 Docker 创建新的网络。默认情况下,Docker Compose 会创建 bridge 网络。这是一种单主机网络,只能够实现同一主机上容器的连接。当然,也可以使用 driver 属性来指定不同的网络类型。
  • volumes 用于指引 Docker 来创建新的卷。
version: '3'
services:
  my-mysql:
    build:
      context: ./mysql
    environment:
      MYSQL_ROOT_PASSWORD: admin
    restart: always
    container_name: my-mysql
    volumes:
    - /data/edu-bom/mysql/lagou:/var/lib/mysql
    image: mysql:5.7
    ports:
      - 3306:3306
    networks:
      my-net:
  my-eureka:
    build:
      context: ./edu-eureka-boot
    restart: always
    ports:
      - 8761:8761
    container_name: edu-eureka-boot
    hostname: edu-eureka-boot
    image: edu-eureka-boot:1.0
    depends_on:
      - my-mysql
    networks:
      my-net:
networks:
  my-net:
volumes:
  my-vol:

常用命令汇总

启动服务

docker-compose -f filename up -d

停止服务

docker-compose down

列出所有运行容器

docker-compose ps

查看服务日志

docker-compose logs

构建或者重新构建服务

docker-compose build

启动服务

docker-compose start

停止已运行的服务

docker-compose stop

重启服务

docker-compose restart

docker私有仓库

仓库镜像

docker pull registry:2.7.1

创建仓库容器

docker run -itd -p 5000:5000 --name registry --restart=always registry:2.7.1

添加私服仓库地址

编辑配置文件
vi /etc/docker/daemon.json

增加仓库配置信息
{ "insecure-registries":["192.168.198.101:5000"] }

重启docker
systemctl daemon-reload
systemctl restart docker

查看docker信息确认仓库是否添加
docker info

浏览器测试 http://192.168.198.101:5000/v2/_catalog

上传镜像

docker tag nginx:1.19.3-alpine 192.168.198.101:5000/nginx:v1 docker push 192.168.198.101:5000/nginx:v1

浏览器查看 http://192.168.198.101:5000/v2/nginx/tags/list

企业仓库

harbor官网地址 goharbor.io/

安装harbor

1.解压软件
    cd /data
    tar zxf harbor-offline-installer-v1.9.4.tgz

2.进入安装目录
    cd harbor

3.修改配置文件
    vi harbor.yml

    3.1 修改私服镜像地址
        hostname: 192.168.198.101

    3.2 修改镜像地址访问端口号
        port: 5000

    3.3 harbor管理员登录系统密码
        harbor_admin_password: Harbor12345

    3.4 修改harbor映射卷目录
        data_volume: /data/harbor

4.安装harbor
    4.1 执行启动脚本,经过下述3个步骤后,成功安装harbor私服
        ./install.sh

    4.2 准备安装环境:检查docker版本和docker-compose版本

    4.3 加载harbor需要的镜像

    4.4 准备编译环境

    4.5 启动harbor。通过docker-compose方式启动服务

    4.6 google浏览器访问harbor私服
        http://192.168.198.101:5000
        username: admin
        password: Harbor12345

配置私服

vi /etc/docker/daemon.json
"insecure-registries":["192.168.198.101:5000"]

重启docker服务:
systemctl daemon-reload
systemctl restart docker

新建项目 在harbor中新建公共项目: mydockerimage

登录私服

docker login -u admin -p Harbor12345 192.168.198.101:5000
退出私服
docker logout 192.168.198.101:5000

上传nginx镜像

docker tag mariadb:10.5.2 192.168.198.101:5000/mydocker/nginx:1.19.3-alpine
docker push 192.168.198.101:5000/mydocker/nginx:1.19.3-alpine
docker pull 192.168.198.101:5000/mydocker/mariadb:10.5.2

Dockerfile

基于已有的镜像创建 commit命令

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

常用参数

  • -a :提交的镜像作者;
  • -c :使用Dockerfile指令来创建镜像;
  • -m :提交时的说明文字;
  • -p :在commit时,将容器暂停。

案例

结合docker cp命令自定义nginx的index页面

docker run -itd --name nginx -p 80:80 192.168.198.101:5000/mydocker/nginx:v1

cd /data

echo "laosiji" > /data/index.html

docker cp /data/index.html nginx:/usr/share/nginx/html/index.html

curl localhost

docker container commit -m "update index.html file" -a "wuxi" nginx
192.168.198.101:5000/mydocker/nginx:v2

docker images

docker rm -f nginx

docker run -itd --name nginx -p 80:80 192.168.198.101:5000/mydocker/nginx:v2

curl localhost

docker push 192.168.198.101:5000/mydocker/nginx:v2

Dockerfile命令

image.png

build命令

docker build 命令用于使用 Dockerfile 创建镜像。

docker build [OPTIONS] PATH | URL |

常用参数

build命令参数特别多。这里只给大家介绍几个常用的参数,如果小伙伴们想了解更多内容,请参考 docker官网手册

  • --build-arg=[] :设置镜像创建时的变量;
  • -f :指定要使用的Dockerfile路径;
  • --rm :设置镜像成功后删除中间容器;
  • --tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置 多个标签。

制作镜像

docker build --rm -t 192.168.198.101:5000/mydocker/mysql:5.7 .
docker images

运行镜像

docker run -itd --name mysql --restart always -p 3306:3306 -e
MYSQL_ROOT_PASSWORD=admin 192.168.198.101:5000/mydocker/mysql:5.7

docker logs -f mysql

docker exec -it mysql bash
date
观察时间是否与windows系统的时间一致。

测试mysql连接

docker exec -it mysql bash
mysql -uroot -padmin