前言
参考资料:
https://blog.csdn.net/m0_49960764/article/details/124292208?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166400183616782391893670%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166400183616782391893670&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-4-124292208-null-null.142^v50^new_blog_pos_by_title,201^v3^control_1&utm_term=docker&spm=1018.2226.3001.4187
https://blog.csdn.net/qq_39135287/category_9492725.html
安装
环境信息
[root@bogon run]# uname -r
3.10.0-1160.el7.x86_64
[root@bogon run]# 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"
步骤
uname -r #查看系统内核版本
cat /etc/os-release #查看系统版本
# 卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 下载依赖包
yum install -y yum-utils
# 设置阿里云的Docker镜像仓库 注意,这里是在配置yum的仓库,用于下载dokcer本身
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum软件包 <更新索引的时候出错,即centos8没有该参数,解决办法为:去掉fast参数> <安装时没遇到>
yum makecache fast
# 下载docker <一般情况下安装社区版>
yum install docker-ce docker-ce-cli containerd.io # 安装社区版
# 启动相关
systemctl start docker # 启动Docker
docker version # 查看当前版本号,是否启动成功
systemctl enable docker # 设置开机自启动
# docker版hello world
docker run hello-world
# docker卸载 <记录下,刚安装了,就别下载了>
yum remove docker-ce docker-ce-cli containerd.io # 卸载依赖
rm -rf /var/lib/docker # 删除资源 . /var/lib/docker是docker的默认工作路径
# 配置阿里云镜像服务,这里是配置的image镜像库,和上面的不一样
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://axvfsf7e.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
命令
基础
systemctl start docker # 启动
systemctl stop docker # 关闭
systemctl restart docker # 重启
systemctl status docker # 状态
systemctl enable docker # 开机自启动
docker version #查看docker的版本信息
docker info #查看docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令(可查看可选的参数)
镜像
# 查看镜像列表
# -a/--all 列出所有镜像
# -q/--quiet 只显示镜像的id
docker images
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 21 months ago 141MB
# REPOSITORY 镜像的仓库源
# TAG 镜像的标签
# IMAGE ID 镜像的id
# CREATED 镜像的创建时间
# SIZE 镜像的大
# 搜索镜像
docker search 镜像名
# -f, --filter filter Filter output based on conditions provided
# --format string Pretty-print search using a Go template
# --limit int Max number of search results (default 25)
# --no-trunc Don\'t truncate output
# 搜索收藏数大于3000的mysql镜像
docker search mysql --filter=STARS=3000
# 拉取镜像
docker pull 镜像名 # 不加tag默认拉取最新
docker pull 镜像名:tag
# 运行镜像
docker run 镜像名
docker run 镜像名:Tag
# 删除镜像
#删除一个
docker rmi -f 镜像名/镜像ID
#删除多个 其镜像ID或镜像用用空格隔开即可
docker rmi -f 镜像名/镜像ID 镜像名/镜像ID 镜像名/镜像ID
#删除全部镜像 -a 意思为显示全部, -q 意思为只显示ID
docker rmi -f $(docker images -aq)
# 保存镜像
docker save 镜像名/镜像ID -o 镜像保存在哪个位置与名字
# 加载镜像
docker load -i 镜像保存文件位置
# 分离新的镜像
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
# 构建镜像
docker build
# 查看镜像历史
docker history 镜像名/镜像ID
# 查看镜像元信息
docker inspect 镜像名/镜像ID
容器
# 查看正在运行容器列表
# -a 列出所有容器的运行记录
# -n=? 显示最近创建的n个容器
# -q 只显示容器的编号
# -s 显示总文件大小
docker ps
# 查看所有容器
docker ps -a
# 运行镜像
# -it 表示 与容器进行交互式启动
# -d 表示可后台运行容器 (守护式运行)
# --name 给要运行的容器起的名字
# -p 宿主机端口:容器端口
# --restart=always 该容器随docker服务启动而自动启动
# -v /var/lib/redis/data/:/data 挂载数据卷,必须在容器启动的时候就挂载
# -v 容器内路径 #匿名挂载
# -v 卷名:容器内路径 #具名挂载,使用较多
# -v /宿主机路径::容器内路径 #指定路径挂载
# -v 卷名:容器内路径:ro/rw ro:只读 rw:可读写
# -P 随机指定端口(大写的P)
# -m 设置容器使用的最大内存
# -e 设置环境变量
# --privileged 给予更高的权限,可以解决部分权限问题,但也带来安全风险,谨慎使用
docker run -it -d --name 要取的别名 -p 3305:3306 镜像名:Tag /bin/bash
# 这里-c的选项是sh终端的,并不是run的选项参数,后面加/bin/sh相当于调用容器内sh终端执行-c内的命令
docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
# 停止容器
docker stop 容器名/容器ID
# 删除容器
# -f 强制删除
# -v 删除与容器关联的卷,目前测试是匿名卷会直接删除,具名卷需要指定才能删除,目前没有测试
# -l 移除容器间的网络连接,而非容器本身
#删除一个容器
docker rm -f 容器名/容器ID
#删除多个容器 空格隔开要删除的容器名或容器ID
docker rm -f 容器名/容器ID 容器名/容器ID 容器名/容器ID
#删除全部容器
docker rm -f $(docker ps -aq)
# 进入容器 /bin/bash表示执行该命令,进入bash终端,其实也可以执行其他命名,比如ls查看文件,dash进入终端
docker exec -it 容器名/容器ID /bin/bash
# 退出容器
exit # 非后台运行的容器会被关闭
快捷键:Ctrl + p + q
# 重启容器
docker restart 容器ID/容器名
# 启动容器
docker start 容器ID/容器名
# kill 容器
docker kill 容器ID/容器名
#从容器内拷出
docker cp 容器ID/名称: 容器内路径 容器外路径
#从外部拷贝文件到容器内
docker cp 容器外路径 容器ID/名称: 容器内路径
# 查看日志
docker logs -f --tail=要查看末尾多少行 默认all 容器ID
# 更换容器名
docker rename 容器ID/容器名 新容器名
# 提交镜像
docker commit -m="提交信息" -a="作者信息" 容器名/容器ID 提交后的镜像名:Tag
# 查看容器中进程信息
docker top 容器id
# 查看镜像的元数据
docker inspect 容器id
# 进入容器
docker exec -it 容器id /bin/bash
# 导出容器文件
docker export 容器名/容器ID -o 位置
# 导入容器文件为镜像
docker import 文件
# 查看容器资源使用情况
docker stats 容器名/容器ID
#
docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
# 查看挂载情况
docker volume ls
save和export的区别
docker save的是镜像,docker export的是容器;
docker load 用来加载镜像包,import用来载入容器包;
docker load不能对载入的镜像重命名,而docker import可以为镜像指定命名;
两者导入后都是为镜像
kill和stop的区别?
被kill杀死容器,进入stopped状态被重新start后,会开启新的进程号;
被stop停掉的容器,再次被重新start后,进程号不变,还是原来的。
kill命令比较生猛,不管容器死活,直接给系统发送SIGKILL的系统信号强行kill掉进程,就是要用kill -9干掉容器;
stop比较温柔,先给容器发送一个TERM信号,给容器充足时间(默认10秒)保存数据,让容器自动安全停止运行,超时后再给系统发送SIGKILL的系统信号强行kill掉进程,最后转变为stop状态。
使用docker stop -t [s, default 10],可调整超时时间(docker stop -t 20 容器ID/容器名)
网络
理论
我们每启动一个docker容器,docker就会给docker容器分配一个id,我们只要安装了docker,就会有一个网卡docker0
每增加一个容器就会增加一对虚拟设备接口
宿主机和容器、容器之间通过ip可以互相ping通
测试
docker run -d -it --name centos1 centos:7
# --link 会在centos2的/etc/hosts增加centos1的信息,这样可以让c2通过名字ping通c1,但是c1还是只能通过ip
docker run -d -it --name centos2 --link centos1 centos:7
# 查看网络的配置
docker network ls
<<<
# 网络模式
# bridge: 桥接模式,桥接 docker 默认,自己创建的也是用brdge模式
# none: 不配置网络
# host: 和宿主机共享网络
# container:容器网络连通!(用的少, 局限很大)
NETWORK ID NAME DRIVER SCOPE
54bb6b69df1a bridge bridge local
97734bea8684 host host local
fb749a374109 none null local
>>>
# 查看网络的元信息,bridge的可以看到相关的容器配置了该网络
docker network inspect be0679d23977
# 创建自己的网络,好处是不需要--link了,docker自动维护关系
# --gateway指定了路由
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 启用两个指定我网络的容器,互相之间通过容器名ping通
# docker exec -it centos01 ping centos02
docker run -d -it --name centos01 --net mynet centos:7
docker run -d -it --name centos02 --net mynet centos:7
# 连通网络,注意,此时网络会分配给容器一个新的ip,旧的依旧保留,该网络下的其他容器可以通过容器名或新ip ping通
docker network connect mynet centos1
docker exec -it centos1 ping tomcat-net-01
日志
# 怎么让自定义的日志,在docker上打印呢
# 参考tomcat怎么打印日志到容器的
# 这里打印的是容器的日志,输出到控制台的日志,如果想打印的话,可以直接输出到控制台
docker logs [OPTIONS] CONTAINER
# -f # 跟踪日志输出
# --since # 显示某个开始时间的所有日志
# -t # 显示时间戳
# -n # 仅列出最新N条容器日志(默认为“全部”)
运维
# 查看docker工作目录
docker info | grep "Docker Root Dir"
# 查看docker磁盘占用总体情况
du -hs /var/lib/docker/
# 查看Docker的磁盘使用具体情况
docker system df
# 删除异常停止的容器
docker rm `docker ps -a | grep Exited | awk '{print $1}'`
# 删除名称或标签为none的镜像
docker rmi -f `docker images | grep '<none>' | awk '{print $3}'`
常用软件
docker ui
docker search dockerui
docker pull abh1nav/dockerui
docker run -d --privileged --name dockerui -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock abh1nav/dockerui
#放开物理机的9000端口对应Docker容器的9000端口
curl localhost:9000
http://172.16.16.200:9000
portainer
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
# 测试
curl localhost:8088
# 外网访问
http://172.16.16.200:8088
admin
admin1234
nginx
# 拉取镜像
docker pull nginx
# 运行
docker run -d --name nginx -p 3344:80 nginx
# 访问
http://172.16.16.200:3344
tomcat
docker pull tomcat
docker run -d -p 3355:8080 --name tomcat01 tomcat
# 进入容器
docker exec -it tomcat01 /bin/bash
# 将内容复制到目录下,才能看到文件
cp -r webapps.dist/* webapps
# 访问
http://172.16.16.200:3355
mysql
docker pull mysql:5.7
docker run -d -p 3310:3306 -v /make/dockerdata/mysql/conf:/etc/mysql/conf.d -v /make/dockerdata/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root1234 --name mysql01 mysql:5.7
redis
# 拉取镜像
docker pull redis:6
# 运行
# redis-server /usr/local/etc/redis/redis.conf --appendonly yes 后边的这些命令,我理解是自己指定命令替换Dockerfile中指定的CMD命令
docker run -d -p 6372:6379 -it --name=myredisx3 -v /make/dockerdata/redis/data:/data -v /make/dockerdata/redis/config/redis.conf:/etc/redis/redis.conf redis:6 redis-server /etc/redis/redis.conf --appendonly yes
redis配置文件地址:
https://gitee.com/albert_char/redis_config?_from=gitee_search
# redis.conf配置文件需要修改四处地方:
1、注释掉bind 127.0.0.1,即#bind 127.0.0.1,这里的bind指的是只有指定的网段才能远程访问这个redis,注释掉后,就没有这个限制了;redis6的是bind 127.0.0.1 ::1改为bind * -::*
2、把protected-mode属性设置成no (默认是yes, 禁止了远程访问)
3、把daemonize属性设置成no (表明需要在后台运行)
4、找到# requirepass foobared,删除前面的注释符号#,并把foobared修改成自己的密码 或者 另起一行 requirepass 自己的密码
registry
# 拉取镜像
docker pull registry
# 运行镜像
docker run -d -p 5000:5000 --name=registry --restart=always -v /make/dockerdata/image_registry:/var/lib/registry registry
# 查看镜像
http://172.16.16.200:5000/v2/_catalog
# 修改daemon.json配置文件
cd /etc/docker
vim daemon.json
>>>
"insecure-registries": ["Linux的ip地址:5000"]
<<<
# 重启docker服务
systemctl restart docker
# 本地镜像上传
# 标记
docker tag 镜像ID/镜像名称[:版本号] Linux的ip地址:5000/镜像名称[:版本号]
# 上传
docker push Linux的ip地址:5000/镜像名称[:版本号]
# 拉取
docker pull Linux的ip地址:5000/镜像名称[:版本号]
# 查看具体镜像版本
http://172.16.16.200:5000/v2/镜像名/tags/list
http://172.16.16.200:5000/v2/tomcat/tags/list
Dockerfile
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN [“command” , “param1”,“param2”] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD [“command” , “param1”,“param2”] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
CMD 和 ENTRYPOINT 区别
CMD 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
a文件:
FROM centos:7
CMD ["ls","-a"]
b文件:
FROM centos
ENTRYPOINT ["ls", "-a"]
build文件后执行:
docker run a -l
docker run b -l
执行上面两个命令,前者会报错,后置可以执行
因为前者会用 -l 替换 "ls","-a"
后者是追加: "ls", "-a -l"
centos定义
FROM centos:7
MAINTAINER fjding<dingfujing@gmail.com>
ENV MYPATH /user/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
RUN yum -y install less
EXPOSE 80
# 这里的目的是保持一个进程,让容器不关闭,像tomcat就不需要是因为它自己启动的tomcat进程一直在运行
ENTRYPOINT /bin/bash
docker compose
理论
Docker Compose是一个用来定义和运行复杂应用的Docker开源项目,负责实现对Docker容器集群的快速编排,它允许用户通过一个单独的docker-compose.yml模板文件(YAML格式) 来定义一组相关联的应用容器为一个项目,在配置文件中,所有的容器通过 services 来定义,然后使用 docker-compose 脚本来启动、停止和重启应用。
安装
参照软件/linux/docker
docker-compose模板
# 指定版本
version: '3'
# 定义服务
services:
# 服务名,必须唯一
centos1:
# 构建镜像时,Dockerfile所在目录的路径 可以是绝对路径,也可以是相对 docker-compose.yml文件的路径)
build: ./dir
# 指定网络
networks:
- mynet
# 设置容器启动顺序
depends_on:
- mysql1
centos2:
# 指定服务所使用的镜像,和build二选一
image: centos:7
# 指定容器名称。如果不指定默认将会使用 项目名称_服务名称_序号这样的格式
container_name: mycentos2
tomcat1:
# 暴露端口,<<如果Dockerfile指定了,这里还需要指定嘛?>>
ports:
- "4001:4001"
- "4002:4002"
# 程序仅监视容器状态,针对容器内的应用,通过健康检测进行
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s # 时间间隔
timeout: 10s # 超时时间
retries: 3 # 重试次数
# 为容器添加元信息
labels:
com.startupteam.description: "webapp for a strtup team"
# 重启策略
restart: always
# 数据卷挂载
volumes:
- /make/dockerdata/logs:/usr/local/tomcat/logs
# 数据卷名称前面会自带项目名称(当前docker-compose.yml所在目录的名称)
- t1webapps:/usr/local/tomcat/webapps
redis1:
image: redis:6.0
# 覆盖容器启动后默认执行的命令,即:覆盖DockerFile中的CMD或镜像的启动命令
command: ["redis-server", "--appendonly", "yes"]
mysql1:
image: mysql:5.7
# 设置环境变量
environment:
MYSQL_ROOT_PASSWORD: 123456
# 只给定名称的变量会自动获取运行Compose主机上对应变量的值
SESSION_SECRET:
# 从以.env结尾的文件中获取环境变量
env_file:
- ./mysql.env
# 定义网络
networks:
mynet:
# 是否使用外部的网络,如果使用,必须提前创建,如果使用自己的在服务移除的时候网络也会被移除,外部的不会
external: true
实战
version: '3'
services:
tomcat:
image: tomcat:9
container_name: app
ports:
- "8001:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001"]
interval: 1m30s # 时间间隔
timeout: 10s # 超时时间
retries: 3 # 重试次数
labels:
com.startupteam.description: "webapp for a strtup team"
networks:
- mynet
depends_on:
- mysql1
- redis1
redis1:
image: redis:6.0
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6371:6379"
networks:
- mynet
mysql1:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 123456789
ports:
- "3301:3306"
networks:
- mynet
networks:
mynet:
命令
# docker-compose.yml所在目录就是项目名
# 命令执行下无docker-compose.yml文件,则需要-f指定文件,如果使用-f指定,则配置文件的相对路径就是基于-f指定文件的路径
# service可选,不指定,则启动所有
# -d后台启动,推荐
docker-compose up -d [service]
#停止服务
docker-compose down [service]
# 列出服务
docker-compose ps [service]
# 删除服务
# -f, --force 强制直接删除,包括非停止状态的容器
# -v 删除容器所挂载的数据卷
docker-compose rm [options] [service]
# 进入服务内部
docker-compose exec service服务名称 /bin/bash 或 /bin/sh
# 查看日志
docker-compose logs [service]
# 查看服务内运行的进程
docker-compose top [service]
# 启动服务
docker-compose start [service]
# 停止服务
docker-compose stop [service]
# 强制停止服务
docker-compose kill [service]
# 重启服务
docker-compose restart [service]
harbor
安装
捡软件/linux/docker
使用
项目-新建项目
公开:拉取不需要登录,推送需要
非公开:拉取和推送都需要登录
推送:
docker login 172.16.16.200:5000
docker tag tomcat:9 172.16.16.200:5000/test/app:1.0
docker push 172.16.16.200:5000/test/app:1.0
拉取:
docker pull 172.16.16.200:5000/test/app:1.0