docker

底层技术是用的linux LXC容器技术。

image-20210519144912437

image-20210519145542903

为什么使用docker?

  • 更高效的利用系统资源
  • 更快的启动时间
  • 一致的运行环境
  • 持续交付和部署
  • 更轻松的迁移
  • 更轻松的维护和扩展

容器和虚拟机比较

image-20210520195557034

1.docker三个概念

  • image 镜像

    提供容器所需要使用到的资源,就相当于模板
    
  • 仓库

    仓库使Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库
    
  • 容器

    容器就镜像·运行的实体,容器可以被创建、启动、停止、删除、暂停等。
    
docker 面向对象
镜像
容器 对象

2.镜像分层

假如有三个服务分别为nginx redis es 他们三个包中都有一个简化版的linux 。如果每个包都有linux,那么久会同时运行三个linux,就会产生冗余。
镜像分层就是,这几个服务共用一个简化版的linux,假如nginx,redis都需要用到c++的开发环境,那就会在Linux上多加一层,c++的开发环境,使他们共用,假如还有其他依赖,那么就会在分层。
2.1当容器启动时,一个新的可写层被加载到镜像的顶部。这一层就叫容器层,容器层之下的都叫镜像层。

Volume数据卷

宿主机的目录映射到容器中的目录,应用程序在容器汇中的目录读写数据会同步到宿主机上,这样容器产生的数据久可以持久化了,比如我们的数据库容器,就可以把数据存储到我们宿主机上的真实磁盘中。

注册中心

docker用

registry来保存 用户的镜像,registry有公共1和私有两种。

选择镜像原则,优先选择官方镜像,没有官方镜像,就是使用是星多的。

安装docker

配置docker需要的配置环境
 yum install -y yum-utils
 
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.re

yum-config-manager --enable docker-ce-nightly
安装docker
yum install docker-ce docker-ce-cli containerd.io  ##检查一下密钥是不是060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35 如果不是则东西被篡改了
启动docker
systemctl start docker
查看docker版本
docker --version
Docker version 20.10.6, build 370c289
测试docker
docker run hello-world
查看docker容器的运行状态和简要信息
docker stats
docker info
查看容器详细信息
docker inspect [容器ID | 容器名] 

配置docker加速
[root@master ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "http://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}
镜像是什么:

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

联合文件系统UnionFS:

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

特性:

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

Docker镜像加载原理:
bootfs主要包含bootloader 和 kernel,boot loader 主要时引导加载kernel,linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs,在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版。
对于一个精简的OS rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为最底层用Host和Kernal,自己只需要提供rootfs就行了。由此可见对于不同的linux发行班,bootfs基本是一致的,rootfs会有差别,因此不同的发现版可以共用bootfs。
docker镜像特点
只读,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作容器层。“容器层”指下的都叫"镜像层"。
多个镜像都从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份basw镜像,同时内存中也只需加载一份base镜像,就可以为所有同期服务了
搜索镜像
docker search centos
获取镜像,加入我们这里获取一个centos的镜像
 docker pull centos
 docker pull centos:lastest ##最新版本
 docker pull centos:[版本号] 
docker run的运行过程
docker run hello-world
Unable to find image 'hello-world:latest' locally ##提示本地找不到镜像
latest: Pulling from library/hello-world ##拉最新的镜像
b8dfde127a29: Pull complete 
Digest: sha256:5122f6204b6a3596e048758cabba3c46b1c937a46b5be6225b835d091b90e46c
Status: Downloaded newer image for hello-world:latest ##拉取

Hello from Docker!

image-20210522160154101

查看镜像
docker images
删除镜像
docker rmi centos
搜索镜像
docker search nginx
导出镜像
docker save -o centos.tar centos
docker save > centos.tar centos 
导入镜像
docker load < centos.tar 
docker load  -i centos.tar

client客户端

容器相关命令

启动容器
docker run nginx ##这里会直接卡住
查看容器
docker ps ##查看运行的容器
docker ps -a ##查看所有容器
docker ps -l ##最后一次运行的容器
docker ps -f status=[状态] ##查看对应容器
docker ps -n ##查看几个
  • -i 标识运行容器
  • -t 标识启动容器后进入命令行
  • -v 标识目录映射关系
  • -d 后台
  • -p 指定映射端口
  • -P 随机映射端口
创建启动容器并进入
	 docker run --name mynginx -p 80:8080 nginx   ##指定端口映射
 docker run --name mynginx -P nginx  ##随机映射
创建启动容器不进入
 docker run  -d --name mynginx -p 80:8080 nginx ##守护模式创建容器

进入守护进程容器
docker exec -it  [容器ID | 容器名] /bin/bash
创建容器并进入容器
docker run  -d --name mycentos centos /bin/bash
退出容器
exit
停止启动容器
 docker stop [容器ID | 容器名]
 docker start [容器ID | 容器名]
删除容器
docker rm [容器ID | 容器名]  ##需要暂停容器
docker rm -f [容器ID | 容器名] ##删除运行中的容器
 docker rm -f $(docker ps -a) ##删除所有容器
文件拷贝

文件拷贝到容器

docker cp [复制的文件] [容器名称]:[目的目录或者文件名]‘

容器文件拷贝到宿主机

docker cp [容器名|容器ID]:[容器内目录或者文件] [本机目录]
目录挂载
可以将容器挂载到本机的某个目录,从而可以通过修改挂载的本机目录来修改这个容器。
但是容器被删除的时候,宿主机内容不会被删除。如果多个容器挂载到同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

匿名挂载

不指定本主机目录只指定容器目录,它会自动创建一个匿名卷在本主机的/var/lib/docker/vloumes

docker run -di --name nginx2 -p 81:80 -v [容器目录] nginx

具名挂载

目录也在/var/lib/docker/vloumes

docker run -di -d -p 8081:80 --name nginx4 -v [目录名字]:[容器目录] nginx 

指定目录挂载

docker run -di --name nginx2 -p 81:80 -v [本机目录]:[容器目录] nginx ##容器目录指定了它会自动创建 

查看目录挂载关系

docker inspect  ##可以查看容器的所有信息包括ip地址什么的
docker volume inspect [卷名]

只读/只写

docker run -di -d -p 8082:80 --name nginx5 -v [容器目录]:[容器名]:[ro|rw] nginx ##只读

vloumes-from(继承)

docker run -di -d -p 81:80 --name nginx7 --volumes-from [被继承人容器]:ro nginx 

构建镜像

通过centos7镜像,在里面安装jdk和redis,然后作为一个新的镜像。

创建容器

 docker run -di --name mycentos centos:7

拷贝资源

先把redis和jdk的包上传到本主机

docker cp jdk-8u181-linux-x64.tar.gz mycentos:/

docker cp redis-4.0.8.tar.gz mycentos:/  

安装资源

docker exec -it mycentos bash ##进入容器
mkdir /usr/local/jdk
mkdir /usr/local/redis
tar zvxf jdk-8u181-linux-x64.tar.gz -C /usr/local/jdk/  
tar zvxf redis-4.0.8.tar.gz -C /usr/local/redis/ 
cat /etc/profile
export JAVA_HOME=/usr/local/jdk/jdk1.8.0_181
export PATH=$PATH:$JAVA_HOME/bin
java -version
构建镜像
docker commit [容器名|容器ID] [新镜像名]:[标签]
-a 镜像作者
-m 信息
docker commit -a='tanc' -m='redis and jdk ' mycentos mycentos:7
[root@master ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mycentos      7         01413e360209   8 seconds ago   593MB
 docker stop mycentos
 docker run -di --name  mycentos7 mycentos:7
 镜像就创建成功!

Dockerfile

Dockerfile 是创建镜像的所有命令的文本文档。

Dockerfile的运行规则
  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交
Dockerfile执行的大致流程
  • docker从基础镜像运行一个容器
  • 执行一条指令并对容器作出修改
  • 执行类似docker commit的操作提交一个新的镜像层
  • docker在基于刚提交的镜像运行一个新容器
  • 执行dockerfile中的吓一跳指令知道所有指令都执行完成

从应用软件的角度来看Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Dokcer容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Dokcer容器则涉及部署以合运维,三者缺一不可。

FROM
语法 FROM  [image]:[tag]

构建来自于哪个基础镜像

有个镜像里面什么都没有只有基础的命令名字叫scratch

MAINTAINER
语法 MAINTAINER
指明镜像维护者及器联系方式,
LABEL
语法 LABEL [key]=[value]
指定镜像标签或者作者
RUN
语法 RUN [shell命令]
构建镜像运行的shell命令,比如构建的新镜像中我们想在/usr/local
ADD
语法 ADD [源文件]  [目标文件]
拷贝文件,支持自动下载和解压
COPY
语法 COPY [源文件]  [目标文件]
拷贝文件,不支持自动下载和解压
EXPOSE
语法 EXPORT [端口] [端口] / [协议]
暴露容器运行时监听端口给外部
ENV
语法 ENV [键] [值]
设置容器内环境变量
CMD
语法 CMD [命令]
启动容器时执行的shell命令,在Dockerfile中只能有一条CMD指令,有多条就只会最后一条生效。如果在创建容器时给定了shell命令,那么这个就会被覆盖掉
  • shell格式 : CMD <命令>
  • exec 格式:CMD ["可执行文件,“参数1”,“参数2”....]
  • 参数列表格式:CMD[“参数1”,“参数2”....]在指定ENTPYPOINT指令后,用CMD指令具体参数。

ENTRYPOINT

语法 ENTRYPOINT [命令]
和cmd一样但是不会被覆盖掉,docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合
WORKDIR
语法 WORKDIR [目录]
为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录,或者登录目录
VOLUME
指定容器挂载到宿主机
ONBUILD

当构建一个被继承的Dockerfile时运行命令父镜像的onbuild被触发

就是当他作为要被继承的主镜像的时候他就会触发的命令或者机制

image-20210527202621231

创建Dockerfile

注意:Dockerfile可以创建有个文件夹在存放Dockerfile 也可以不用建议是用。

Dokcerfile 文件就以Dockerfile或者其他命名,没有任何后缀。

[root@master dockerfile]# cat /usr/local/dockerfile/Dockerfile 
FROM centos:7
LABEL zuozhe='tanc'
WORKDIR /url/local
RUN mkdir -p /usr/local/jdk & mkdir -p /usr/local/redis
ADD jdk-8u181-linux-x64.tar.gz /usr/local/jdk
ADD redis-4.0.8.tar.gz /usr/local/redis
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_181 
ENV PATH=$PATH:JAVA_HOME/bin
CMD ['/url/local/root/redis-4.0.8/utils/install_server.sh','run']
使用Dockerfile
docker build -f Dockerfile -t mycentos:7 .
-f指定dockerfile文件
-t 创建的镜像名字
. 要调用的东西存在位置

docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mycentos      7         2d0914b2ddf3   3 minutes ago   593MB
docker run -it mycentos:7 
查看镜像变更历史
docker history [镜像名]

上传镜像到私有仓库

登录dockerhub

docker login
拉取私有仓库包
docker pull registry
修改配置文件daemon.json

添加

{
"insecure-registries":["192.168.137.10:5000"]
}
创建registry容器
docker run -di -p 5000:5000 -v /opt/registry/:/var/lib/registry --name registry registry
打开浏览器输入
http://192.168.137.10:5000/v2/_catalog ## 会显示 就表示成功

{"repositories":[]}
创建标签
docker tag hello-world:tag 192.168.137.10:5000/tanc-hello-world:1.1.1
##查看
docker images
busybox                                latest    d3cd072556c2   6 days ago     1.24MB
192.168.137.10:5000/tanc-hello-world   1.1.1     d1165f221234   2 months ago   13.3kB
上传
docker push 192.168.137.10:5000/tanc-hello-world:1.1.1
在登录浏览器查看
http://192.168.137.10:5000/v2/_catalog
{"repositories":["tanc-hello-world"]}
拉取镜像
 docker run -it --name hello2 192.168.137.10:5000/tanc-hello-world:1.1.1
配置个人仓库证书认证

创建放置密钥的文件

 mkdir -p /usr/local/registry/certs
 
 mkdir -p /usr/local/registry/auth

创建密钥

openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/registry/certs/domia.key -x509 -days 365 -out /usr/local/registry/certs/domain.crt

Common Name (eg, your name or your server's hostname) []: ##在这个选项填仓库ip地址
openssl req 创建证书签名请求等功能
-newkey 创建CSR证书签名文件和RSA私钥文件;
rsa:2048 指定创建RSA私钥长度为2048;
-nodes 对私钥不进行加密;
-sha256 使用SHA256算法
-keyout 创建的私钥文件名称及位置;
-x509 自签发证书格式;
-days 证书有效期
-out 指定CSR输出文件名称和位置
创建密码文件
htpasswd -Bbn root 1234 > /usr/local/registry/auth/htpasswd ##会自动生成文件

[root@master auth]# cat htpasswd 
root:$2y$05$lUmu9uX5dgWaeeVho3YvYOWSfqtEA6ylMz3RMPfwG/aDfHokVcSd
htpasswd
参数 解释
-c 创建一个加密文件
-n 不更新加密文件,只将apache htpsswd命令加密后的用户名密码显示在屏幕上
-m 默认apache htpassswd命令采用MD5算法对密码进行加密
-d apache htpassswd命令采用CRYPT算法对密码进行加密
-p apache htpassswd命令不对密码进行进行加密,即明文密码
-s apache htpassswd命令采用SHA算法对密码进行加密
-b 在apache htpassswd命令行中一并输入用户名和密码而不是根据提示输入密码
-D 删除指定的用户
-B 强制对密码进行bcrypt加密(非常安全)

创建容器,挂载和环境变量

docker run -di --name registry  -p 5000:5000 \
-v /opt/registry/:/var/lib/registry  \
-v /usr/local/registry/certs:/certs \
-v /usr/local/registry/auth/:/auth \
-e "REGISTRY_AUTH=htpasswd"  \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry
登录到仓库
[root@master certs]# docker login 192.168.137.10:5000
Username: root
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
上传容器
docker tag hello-world 192.168.137.10:5000/tc:1
docker push 192.168.137.10:5000/tc:1
退出账号
docker logout 192.168.137.10:5000
查看docker 网络
docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
41e3463787d8   bridge    bridge    local ##桥接
d6940070926d   host      host      local ##使用主机模式
690f3fe16a1f   none      null      local ##没有网络可以自己定义
网络模式 简介
bridge 为每一个容器分配,配置ip等,并将容器连接到一个docker0虚拟网桥,默认为改模式
host 容器将不会虚拟出自己的网卡,配置直加到IP等,而是使用主机IP和端口
none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,ip等
container 新创建的容器不会创建自己的网卡和配置自己的IP,二十和一个指定的容器共享IP,端口范围等。

busybox是一个linux命令集成工具

bridge 网络模式
在桥接模式中,docker守护进程会自动你创建一个docker0,新建的容器会自动桥接到这个接口,附加在上面的任何网卡之间都可以自动转发数据包。
默认情况下,守护进程会创建一对对等的虚拟设备接口veth pair,将其中一个接口设置为容器的eth0接口,另一个阶段放在本主机的命令空间中,类似vethxxx这样的名字命名,从而将宿主机上所有容器都连接到这个内部网络上。

image-20210524161917254

host网络模式
  • host网络模式要在创建容器时通过参数 --net host 或者 --network host
  • 采用host网络模式的docker容器,可以直接使用宿主机的IP地址与外界通信,若宿主机的网卡时应该公有ip,那么容器也拥有这个公有ip,同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换

缺点就是容器缺少网络隔离

image-20210524191859954

创建host网络容器
docker run -it --network host --name hostnet busybox
none网络模式

none模式就是禁止使用网络模式,只有本地回环口,通过--net none指定

创建none

docker run -it --net none --name nonenet busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
/ # 
container网络模式

container网络模式是docker中特别的网络模式,在创建容器时通过参数 --net container:[已经运行的容器名|容器ID] 指定

处于这个模式下容器会共享一个网络线,这两个容器通过回环接口来通讯

image-20210524195015390

创建container

docker run -di  --name mycentos centos:7 ##创建一个容器
[root@master ~]# docker inspect mycentos ##查询这个容器的ip地址
Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                
[root@master ~]#  docker run -it --name container --net container:mycentos busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
92: eth0@if93: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ #           

如果主容器停止或者删除了那么container的网卡也会销毁

[root@master ~]# docker stop mycentos


/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
/ #  ##这里可以看见一张网卡没有了
自定义网络
dokcer提供默认网络使用比较简单,但是为了保证容器中应用的安全性,在实际开发中更推荐使用自定义为了进行容器管理,以及启动容器名称到IP地址的自动DNS解析

docker1.10版本开始,docker daemon实现了一个内嵌的DNS服务,使容器可以直接通过容器名称进行通信,方法很简单,只要在创建容器时使用 --name 为容器命名即可

创建网络
[root@master ~]# docker network create network1
79a06fdc79ebfc9fc41050d7b606f2432df246e7bcac505192dfab218abd1a0e
[root@master ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
41e3463787d8   bridge     bridge    local
d6940070926d   host       host      local
79a06fdc79eb   network1   bridge    local
690f3fe16a1f   none       null      local
docker run -it --name zdynet --net network1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
97: eth0@if98: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
将容器连接到网络命令
docker network connect [OPTIONS] NETWORK [容器名|容器ID]
命令 说明
--alias 为容器添加网络范围别名
--driver-opt 网络驱动程序选项
--ip ipv4地址
--ip6 ipv6
--link 将链接添加到另一个容器
--link-local-ip 为容器添加本地链接地址

docker create

名称,简写 默认 描述
--attachable API 1.25以上 启用手动容器附件
--aux-address 网络驱动程序使用的辅助IPv4或IPv6地址
--config-from API 1.30+ 从中复制配置的网络
--config-only API 1.30+ 创建仅配置网络
--driver-d bridge 驱动程序来管理网络
--gateway 主子网的IPv4或IPv6网关
--ingress API 1.29+ 创建集群路由网状网络
--internal 限制对网络的外部访问
--ip-range 从子范围分配容器ip
--ipam-driver IP地址管理驱动程序
--ipam-opt 设置IPAM驱动程序特定选项
--ipv6 启用IPv6网络
--label 在网络上设置元数据
--opt-o 设置驱动程序特定选项
--scope API 1.30+ 控制网络范围
--subnet 代表网段的CIDR格式的子网
自定义网络
默认的桥环模式在容器中只能通过来ip来ping,如果自己创建了个网络模式就可以依靠容器名来互相ping

创建网络

[root@master ~]# docker network create network1

创建network1模式容器

[root@master ~]# docker run -it --name tc2 --net network1 busybox 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@master ~]# docker run -it --name tc1 --net network1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever

使用容器名互ping就能通了

Compose简介
Dockerfile文件让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配好来完成某项任务的情况。
Docker Compose 恰好满足了这样的需求,它是用于定义和运行多容器Docker应用程序的工具,通过Compose,您可以使用YAML文件来配置程序所需要的服务。
docker compose 项目事Docker官方开源的项目,来源于之前的FIg项目,使用Python语言编写。负责实现2对Dokcer容器集群的快速编排。
使用Docker Compose使用的三个步骤为:
  • 使用Dokcerfile文件定义应用程序的环境
  • 使用doccker-compose.yml文件定义构成应用程序的服务,这样它们开源在隔离环境中一起运行;
  • 执行docker-compose up 来创建并启动所有服务
安装compose
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 

给与docker-compose文件可执行的限权

chmod +x /usr/local/bin/docker-compose

将docker-compose文件链接到/usr/bin、

ln -s /usr/local/bin/docker-compose  /usr/bin/

查看docker-compose版本

docker-compose --version
docker-compose version 1.29.2, build 5becea4c
开始使用docker-compose!

创建一个用于存放compose文件的目录

[root@master ~]# mkdir composetest

在composetest文件里创建一个名为app.py的文件夹,并写入一下内容

[root@master composetest]# cat app.py 
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

在composetest文件夹中创建一个requirements.txt文件

容器的生命周期

如果这个容器里PID为1的进程结束了,那么容器内其就结束了

Docker运行参考

docker run [参数]

启动docker容器时,首先确定要在后台以分离模式还是默认的前台模式运行该容器,

-d=true 分离模式启动容器,以分离模式启动的容器会在用于运行容器的根进程退出时退出。可以与--rm一起使用,一起用则代表容器退出或者退出守护进程时将容器删除。

注意:不要将systemctl 和· service之类的命令传递给分离的容器

-d 不指定任何参数就是前台模式,可以在容器中启动进程并将控制台附加到进程的标准输入,输出和标准错误。

TTY :终端

-a=[ ]	附加到“STDIN(标准输出)”、“STDOUT(标准)”和/或“STDERR(标准错误)”
-t	分配给伪tty
--sig-proxy=true : 将所有接收到的信号代理给进程(仅限非TTY模式)
-i	即使未连接,也保持标准输入打开

如果 没有指定-a 则docker将同时附加到stdout和stderr

对于交互式shell,必须-i -t 一起使用才能为容器进程分配tty

集装箱标识

Name

可以通过三个来识别集装箱

UUID 长标识
UUID 短标识
集装箱名字

UUID标识符来之Docker守护程序。如果未使用--name 选项分配容器名称,则守护程序会生成一个随机的UUID。

[:tag]

可以通过添加image[:tag] 命令来指定要用于运行容器的映像版本。