目录
docker 容器
1.docker是什么?
软件的打包技术,容器技术
2.docker的安装
# 安装docker
yum install docker -y
# 启动docker
systemctl start docker
# 设置开机自启
systemctl enable docker
# 体验docker版nginx最新版
docker run -d -p 80:80 docker.mirrors.ustc.edu.cn/library/nginx
# 体验docker版nginx 1.16
docker run -d -p 81:80 docker.mirrors.ustc.edu.cn/library/nginx:1.16
# 体验wordpress
docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d docker.mirrors.ustc.edu.cn/library/mysql:5.7
docker run -d --link mysql:mysql -p 85:80 docker.mirrors.ustc.edu.cn/library/wordpress:5.6
3.镜像常用命令
# 从中科大docker仓库下载docker官方镜像wordpress
docker pull docker.mirrors.ustc.edu.cn/library/wordpress:5.4
# 从中科大docker仓库下载用户t29617342上传的wordpress
docker pull docker.mirrors.ustc.edu.cn/t29617342/wordpress:5.4
docker info 查看docker的信息
docker inspect 查看某一镜像的信息
docker search 搜索镜像(只搜索官方仓库)
docker images 查看本地镜像列表
docker pull 下载镜像,拉取镜像
docker push 上传镜像,推送镜像
docker rmi 删除镜像
docker tag 更改镜像名及版本号 例:docker tag + 源镜像名 镜像名:版本号
docker save 导出镜像(压缩包)
docker save 镜像名 -o docker_nginx1.20.tar.gz
-o output 输出到文件
docker load 导入镜像
docker load -i docker_nginx1.20.tar.gz
-i input 导入指定文件
4.容器的常用命令
# docker 常见命令
docker port + 容器 查看容器端口映射
docker inspect 查看某一容器的信息
docker logs -f + 容器名 实时刷新容器日志
docker run 等于创建+启动
docker ps === docker container ls #参数:-a 查看所有容器
docker stop 停止容器 #例子 docker stop 容器id或者容器名字
docker start 启动容器 #例子 docker start 容器id或者容器名字
docker rm 删除容器 #例子 docker rm 容器id或者容器名字
docker restart 重启重启 #例子 docker restart 容器id或者容器名字
docker exec 进入容器 #例子 docker exec -it 容器id或者容器名字 /bin/bash(/bin/sh)
docker commit 从容器创建一个新的镜像 #例子 docker commit 容器名 镜像别名:版本号
# 删除所有容器
docker rm -f `docker ps -a -q`
docker top 查看容器内进程信息 #例子docker top 容器id或者容器名字
docker stats 查看容器的资源占用情况
docker run参数
# 常用参数
--name 指定容器的名字,且名字唯一
-d 后台运行
-p 端口映射 #例子:-p 宿主机端口:容器端口
--restart=always 设置容器自动开启
-e 环境变量
docker run -d -P -e MYSQL_ROOT_PASSWORD=luobo222 mysql:5.6
--link 容器互联 #例子:--link <容器名name>:<容器别名alias>
当你使用docker run --link参数时,
1. 给新建的容器,添加对应的link容器变量信息,如ip、port等变量
2. 自动给新建的容器,添加hosts文件,主机名解析
docker run --rm --link 0068591ec439 -it centos bash
-v 数据目录映射
三种挂载模式:
1.bind mount(绑定挂载模式):指定宿主机的一个目录挂载
-v 宿主机目录:容器目录:读写模式(ro:设置容器内只读)
例:-v /my_docker_nginx:/usr/share/nginx/html:ro
2.volume模式(自动挂载):docker自动分配宿主机的一个目录,挂载到容器内指定的目录
-v 数据卷目录名:容器内指定的目录:读写模式
例:-v /usr/share/nginx/html
-v luobo_data:/usr/share/nginx/html:ro
可以通过docker inspect查看容器随机分配的目录
docker volume ls # 数据卷的查看
docker volume rm 数据卷名 # 数据卷的删除 注意:要先删除数据卷使用的容器
docker volume prune # 清理无用数据卷
3.tmpfs mount(基于内存的临时挂载模式)
-- volumes-from 容器名 读取某个容器的数据卷
测试常用
docker run -it --rm centos bash
# 不常用参数
-P 随机端口映射,系统随机分配端口映射
--rm 容器挂掉后自动删除,常用于测试环境
-it 开启交互式终端
/bin/bash(/bin/sh) 指定解释器
docker exec:进入正在运行的容器空间内
-it 开启交互式终端
/bin/bash(/bin/sh) 指定解释器
5.Docker网络
docker的网络模式,包含三个概念,network、sandbox、endpoint,我们先来看看这几个概念,有了这些基本概念,才能在使用的过程中,得心应手
network(网络)
docker的所有功能都通过插件形式管理,懂开发的同学或许能理解这种含义(有兴趣的可以阅读docker源码),我们就从运维角度去理解,network属于是一个第三方网络插件,提供了
- 单主机网络 Driver,提供bridge、host、joined container、none四种模式
--net=bridge 这个是默认值,连接到默认的网桥。
--net=host (共用宿主机网络) 告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 --privileged=true,容器会被允许直接配置主机的网络堆栈。
--net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。
--net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
- 多主机网络,有overlay、 macvlan、 flannel模式
network理解就是docker内部的虚拟子网,接入到该network的容器,相互之间可以安全的通信。
sandbox(沙盒)
sandbox实现了容器内部的网络栈 , 提供如下功能
- 虚拟网卡
- 路由表
- DNS
- 防火墙
- 等网络配置
沙盒是linux network namespace, 实现了容器网络和宿主机网络的隔离,形成了完全独立的容器网络环境.
endpoint(端点)
network实现第三方的网络栈,sandbox实现了容器内部的网络栈,这两个怎么连接起来工作?就是通过endpoint,它用于让不同的network namespace进行通信。
endpoint端点,是一对veth pair(虚拟以太网设备,https:/ /wiki. openvz.ong/Virtual_Ethernet_device
)
一端挂在容器里,一端挂在netwark中,作用主要是形成一个可以控制的网络环境出入口,搭建一个桥梁,进行数据传输。
图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eV7TcKSb-1685628445660)(docker命令速记.assets/1-28.png)]
每一个容器都有一个沙盒,并且都可以独立的接入一个network
并且容器还可以支持分别接入多个网络环境
docker网络的具体实现如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FSlCi8aH-1685628445661)(docker命令速记.assets/1-29.png)]
bridge是我们使用docker,默认的网络驱动,顾名思义就是一个网桥。
Overlay俗称隧道网络,能够搭建跨物理主机的虚拟网络隧道,实现跨物理主机的容器集群通道。
手动创建容器网络
创建一个空网络环境,然后手动给容器分配网络
–net=none
docker创建一个容器的流程:
- 创建一对虚拟接口,分别放到本地主机和新容器中。
- 宿主机一端桥接到默认的docker0,且有一个唯一的名字。
- 另一端放入容器里,改名为eth0,该接口只能在容器的命名空间里可见。
- 从网桥可用地址段获取一个空闲ip,分配给容器的eth0,且配置默认路由桥接到宿主机网卡
- 完成这些之后,容器可以使用eth0虚拟网卡和其他容器连接。
1.运行一个没有网络环境的容器,使用 --net=none
docker run -it --rm --net=none centos bash
2.此时的容器没有网络接口
[root@3a23d609903a /]# 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
3.查看容器在宿主机的进程id
# docker的容器,其实是宿主机的一个轻量级的进程
[root@docker01 ~]# docker inspect -f "{
{.State.Pid}}" 3a23
8876
4.手动给容器,创建网络环境(network namespace)
# 该进程的pid号,以及对应的namespace
[root@docker01 ~]# ps -ef |grep 8876
root 8876 8854 0 10:35 pts/0 00:00:00 bash
root 9088 9055 0 11:09 pts/0 00:00:00 grep --color=auto 8876
# 对这个目录下的文件修改,就是直接修改进程信息
# 给这个容器进程,添加网络环境
[root@docker01 ~]# ls /proc/8876
attr environ mem pagemap stack
autogroup exe mountinfo patch_state stat
auxv fd mounts personality statm
cgroup fdinfo mountstats projid_map status
clear_refs gid_map net root syscall
cmdline io ns sched task
comm limits numa_maps schedstat timers
coredump_filter loginuid oom_adj sessionid uid_map
cpuset map_files oom_score setgroups wchan
cwd maps oom_score_adj smaps
5.开始手动给容器添加 netns 目录
mkdir -p /var/run/netns
# 做软连接,把该容器进程的 网络名称空间,连接出来
# 后续直接修改 /var/run/netns/8876,就表示,修改容器内的网络信息
ln -s /proc/8876/ns/net /var/run/netns/8876
6.查看宿主机的网络信息
[root@docker01 ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:6dff:fea0:7db3 prefixlen 64 scopeid 0x20<link>
ether 02:42:6d:a0:7d:b3 txqueuelen 0 (Ethernet)
RX packets 171 bytes 6580 (6.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 41 bytes 3750 (3.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.1.110 netmask 255.255.255.0 broadcast 10.0.1.255
inet6 fe80::f84e:e256:52a3:3ed3 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:82:dd:cb txqueuelen 1000 (Ethernet)
RX packets 61160 bytes 86961825 (82.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 16038 bytes 1108032 (1.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
7.给容器添加,虚拟网络接口 (宿主机执行)
# 添加一对虚拟接口,名字分别是 A 和 B
ip link add A type veth peer name B
# 安装linux的网桥管理工具
yum install bridge-utils -y
# 将自己创建的虚拟网路接口,挂到docker0上
brctl addif docker0 A
# 启用虚拟接口
ip link set A up
8.将B虚拟网络接口,添加到容器内 (宿主机执行)
# 给容器内添加虚拟网络接口
ip link set B netns 8876
# 将容器的网络接口名字 B 修改为 eth0
ip netns exec 8876 ip link set dev B name eth0
# 启动 eth0
ip netns exec 8876 ip link set eth0 up
# 给容器添加一个 ip 地址,并且跟宿主机的 docker0 在同一网段
ip netns exec 8876 ip addr add 172.17.0.50/16 dev eth0
# 添加路由
ip netns exec 8876 ip route add default via 172.17.0.1
指定ip的端口配置
需求,容器内的应用,限制只能让宿主机本地访问
1.指定ip地址进行端口映射
2.通过防火墙限制
docker run -d -p 127.0.0.1:7070:80 nginx
容器互联的配置
–link 参数,指定容器之间的连接
docker run --link <容器名name>:<容器名alias>
当你使用docker run --link参数时
1. 给新建的容器,添加对应的link容器变量信息,如ip、port等变量
2. 自动给新建的容器添加hosts文件,主机名解析
6.0制作docker镜像并上传公开仓库
1.在容器中加入需要的功能
docker exec 进入容器 #例子: docker exec -it 容器id或者容器名字
yum install xx -y
exit
2.从容器创建一个新的镜像。
docker commit 容器名 镜像别名:版本号
docker commit nginx nginx_vim:v1
3.在DockerHub中创建一个仓库,命名为(nginx_vim)
4.上传到官方仓库,要先登陆到镜像仓库
# 登录官方仓库,且提前创建好仓库
docker login
5.标记本地镜像,将其放入某一仓库。
docker tag 镜像名 Docker Hub用户名/镜像别名:版本号
docker tag nginx_vim:v1 rabbo/nginx_vim:v1
6.将本地的镜像上传到镜像仓库,镜像路径必须跟所创建的仓库一致
docker push rabbo/nginx_vim:v1
# docker login后都会在本地存放认证信息:账号密码
cat /root/.docker/config.json
6.5搭建使用私有docker registry
1.运行,部署一个私有的registry服务
# docker已经提供好了一个镜像,就是运行registry服务的
# 查看registry
docker search registry
# 下载且运行registry服务
docker run -d \
--name cc_registry \
--restart=always \
-p 5000:5000 \
-v /opt/data/registry:/var/lib/registry \
registry
2.上述命令就运行了一个空白页面的私有镜像注册服务
该服务,没用提供好看的web界面,而是基于api的形式,管理没有界面的,但是
可以和他进行http的数据交互的一个网站
# api地址如下
http://10.0.1.120:5000/v2/_catalog
访问内容:{"repositories":[]}
3.重命名需提交至仓库的镜像
docker tag nginx 10.0.1.120:5000/my_local_nginx
4.修改docker配置文件,去掉https,基于http的推送(因为客户端发出的是https请求,服务的是http响应处理)
[root@docker01]# vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
],
# 添加如下配置即可
"insecure-registries":["10.0.1.120:5000"]
}
# 重启docker生效
systemctl restart docker
5.推送镜像到仓库
docker push 10.0.1.120:5000/my_local_nginx
6.验证私有镜像
# 浏览器验证
http://10.0.1.120:5000/v2/_catalog
访问内容:{"repositories":["my_local_nginx"]}
# linux验证
curl http://10.0.1.120:5000/v2/_catalog {"repositories":["my_local_nginx"]}
7.从另一台局域网机器下载该镜像
docker pull 10.0.1.120:5000/my_local_nginx
7.Dockerfile脚本
1.编写Dockerfile脚本
[root@docker01 my_docker]# vim Dockerfile
FROM centos:7.6.1810
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo;
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo;
RUN yum makecache fast;
RUN yum install python3-devel python3-pip -y
RUN pip3 install flask
COPY app.py /opt
WORKDIR /opt
EXPOSE 8080
CMD ["python","app.py"]
2.构建Dockerfile,生成新镜像
docker build .
docker build -t "指定镜像的名字" .
-t 指定镜像的tag版本
--no-cache 不用旧缓存
3.修改镜像名
docker tag 镜像id luobo/flask
4.运行该镜像
docker run --name flask01 -d -p 80:8080 luobo/flask
5.查看宿主机80端口
http://127.0.0.1:80
dockerfile主要组成部分:
基础镜像信息 FROM centos:7.8.2003
制作镜像操作指令 RUN yum insatll openssh-server -y
容器启动时执行指令 CMD ["/bin/bash"]
dockerfile指令:
FROM 这个镜像的妈妈是谁?(指定基础镜像)
MAINTAINER 告诉别人,谁负责养它?(指定维护者信息,可以没有)
RUN 构建docker镜像时执行的命令,通常用于,创建目录、安装软件包
ADD 添加宿主机的文件到容器内,且自动解压宿主机文件到容器内(gzip,bzip2,xz,tar)
# 官方建议使用COPY
COPY 从宿主机复制文件 /拷贝到镜像目录中 (保留源文件元数据:权限、访问时间一致)
WORKDIR 设置当前工作目录
WORKDIR /opt 设置当前工作目录为/opt
USER 切换用户
USER luobo 切换为萝卜用户
VOLUME 给它一个存放行李的地方(设置卷,挂载主机目录)
VOLUME /data # 将容器内的/data目录,自动挂载到/var/lib/docker/volumes/目录下
VOLUME ["/data1","/data2"] # 将容器内的/data1,/data2目录,自动挂载到/var/lib/docker/volumes/目录下
EXPOSE 指定对外的端口
ENV 环境变量,无论是构建镜像,还是容器运行,该变量都可以使用
ENV NAME = "luobo"
ENV MYSQL_VERSION=5.6
ARG 只用于构建镜像设置的环境变量,容器运行就消失了
CMD ["参数一","参数二"] 设置容器启动时要执行的命令,CMD能够被docker run后面跟的命令行参数替换
# 例:CMD ["curl","-s","http://baidu.com"]
ENTRYPOINT 设置容器启动时要执行的命令,当指定了ENTRYPOINT之后,CMD的语义就有了变化,是把CMD的内容当作参数传递给ENTRYPOINT指令。
8.docker-compose
批量管理docker容器工具
# centos7安装docker-compose
yum install epel-release.noarch -y
yum install docker-compose -y
# kali安装docker-compose
apt install docker-compose -y
配置文件docker-compose.yml,注释在楼下
vim docker-compose.yml
version: '3'
services:
db:
image: docker.mirrors.ustc.edu.cn/library/mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: docker.mirrors.ustc.edu.cn/library/wordpress:5.4
ports:
- "83:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
注释
vim docker-compose.yml
# docker-compose版本
version: '3'
# 容器
services:
# 容器名字(自定义)
db:
# 声明用什么镜像
image: docker.mirrors.ustc.edu.cn/library/mysql:5.7
# 开机自启
restart: always
# 定义环境变量
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
# wordpress依赖db
depends_on:
- db
image: docker.mirrors.ustc.edu.cn/library/wordpress:5.4
# 端口映射
ports:
- "83:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
常用docker-compose命令
# 创建并启动
docker-compose up -d
# 停止并删除
docker-compose down
# 重启
docker-compose restart
# 停止
docker-compose stop
# 启动
docker-compose start
7:docker-compose启动靶场环境
https://vulhub.org/#/environments/