Docker命令学习
Docker 安装
docker安装
见官网: Install Docker Engine on CentOS | Docker Documentation
安装
# 1. 卸载老版本软件
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2. 安装相关&设置repository
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 3. 安装docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 4. 启动
systemctl start docker
# 5. 设置开机启动
systemctl enable docker
# 6. helloworld
docker run hello-world
阿里云镜像加速
# 登陆阿里云 -> 弹性计算-> 容器镜像服务-> 镜像工具-> 镜像加速器
Docker的常用命令
帮助命令
docker version # 显示docker版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 帮助命令
docker的帮助文档: Docker run reference | Docker Documentation
镜像命令
1. docker images # 查看当前主机的所有镜像
"""
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 months ago 13.3kB
# 镜像的仓库源 标签 镜像id 创建的时间 镜像的大小
"""
docker images -a # 显示所有的镜像
docker images -q # 只列出镜像的id
2. docker search 镜像名 # 搜索镜像
"""
> docker search mysql
"""
docker search --filter=STARS=3000 # 搜索出来的镜像是stars大于3000
3. docker pull 镜像名 # 下载镜像,默认latest
"""
> docker pull mysql
"""
docker pull mysql[:tag] # 可以加tag版本号
docker pull mysql:5.7 # 下载5.7版本的mysql
4. docker rmi -f 镜像名(或镜像id) # 删除镜像
"""
docker rmi -f 镜像id # 删除指定的镜像
docker rmi -f 镜像id 镜像id2 镜像id3 # 删除多个镜像id
docker rmi -f $(docker images -aq) # 删除所有镜像
"""
容器命令
1. 新建容器并启动
docker run [可选参数] image
参数:
--name="myname" # 容器名,用于区分容器
-d # 后台方式运行
-it # 使用交互方式运行,进入容器查看内容
-p # 指定容器的端口
-p 主机端口:容器端口(常用)
-p 容器端口
-P # 随机指定端口
例如:
docker run -it centos /bin/bash
2. 列出正在运行的容器
docker ps # 列出正在运行的容器
docker ps -a # 列出运行的+已运行结束的所有容器
docker ps -n=3 # 显示最近运行的几个容器
docker ps -q # 只显示容器的id
3. 退出容器
exit # 停止容器并退出
ctrl + p +q # 容器不停止退出
4. 删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q | xargs docker rm # 删除所有容器
5. 启动和停止容器的操作
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id # 强制停止一个容器
容器常用其他命令
1. 后台启动容器
docker run -d centos
# 问题:通过docker ps查看发现centos停止了
原因:docker容器使用后台运行,就必须要一个前台进程,docker发现没有应用会自动停止,例如nginx发现没有提供服务,会立刻结束了
2. 查看日志
docker logs [参数] 容器id
参数:
docker logs -tf 容器id # 显示日志, t为时间戳,f为follow
docker logs --tail number 容器id # 显示日志条数
3. 查看容器中的进程信息
docker top 容器id
4. 查看镜像【或容器】的元数据
docker inspect 容器id/镜像
5. 进入当前正在运行的容器
docker exec -it 容器id /bin/bash # 进入容器后开启一个新的终端
docker attach 容器id # 进入当前正在打开的容器终端,不会打开新的终端
6. 从容器内拷贝文件到本地主机上
docker cp 容器id:容器内的路径 目的主机路径
例如:
docker ps 容器id:/root/aa.py /home/fanzone/
7. 查看cpu的状态
docker stats 容器id
练习实战
1. docker安装nginx
# 1. 搜索镜像
docker search nginx
# 2. 下载镜像
docker pull nginx
# 3. 运行测试
docker run -d --name nginx01 -p 3344:80 nginx
2. 安装tomcat
# 官方提供使用
docker run -it --rm tomcat:9.0 # --rm 用于测试,执行结束自动删除容器
# 自己用还是下载启动运行
docker pull tomcat:9.0
docker run -d --name tomcat01 -p 3355:8080 tomcat:9.0
3. 部署es+kibana
# es暴露的端口很多,如何解决?
# es十分耗内存,如何解决?
# es数据需要放到一个安全目录,如何解决? # 挂载解决
docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 添加es的内存限制,修改配置文件,-e 环境配置修改
docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2 # 限制内存最小64,最大512
Docker可视化
portainer
是docker的可视化界面的管理工具,提供一个后台面板供我们操作
docker run -d -p 8088:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Docker镜像讲解
Docker的镜像都是只读的,当容器启动的时候,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器一下的层为镜像层。
commit提交镜像
docker commit -m "提交的信息" -a="作者" 容器id 目标镜像名[:tag]
# 练习:
docker commit -a='fhz' -m "add apps" 02bed854b8ef my_tomcat11:1.0
容器数据卷
什么是容器数据卷?
如果数据都在容器中,那我们将容器删除,数据会丢失!需求:数据可持久化
MySQL,容器删除,数据丢失,需求:将数据可以存储在本地。
容器之间可以有一个数据共享的技术,Docker容器中产生的数据,同步到本地。
这就是卷技术,目录的挂载,将容器内的目录,挂载到本地主机上。
挂载数据卷
法一: 直接使用命令来挂载 -v
例如:
docker run -it -v 主机目录:容器内目录 mysql
docker run -it -v C:/Users/ffz:/home centos /bin/bash
好处:
可以将本地的nginx目录(/usr/share/nginx)与容器内的nginx目录进行挂载,容器会自动同步
法二: 见下Dockerfile
练习安装MySQL
# 1. 获取mysql镜像
docker pull mysql:5.7
# 2. 运行容器,数据挂载
docker run -d -p 3310:3306 -v c:/Users/fanzone/mysql/conf:/etc/mysql/conf.d -v c:/Users/fanzone/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 3. 此时查看容器详细信息
docker inspect mysql01
"""
"Mounts": [
{
"Type": "bind", # bind类型
"Source": "/data",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Volumes": null,
"""
# 4. 启动成功之后
mysql -uroot -P 3310 -p
# 5. 本地创建数据库,查看data目录映射的路径是否正常(一个文件夹)
create database test001;
# 6. 将容器删除,本地数据依然存在,这就实现了本地数据持久化
docker rm mysql01
具名挂载和匿名挂载
# 如何确定是具名挂载还是匿名挂载,还是制定路径挂载
-v 容器内地址 # 匿名挂载, 此时mount type为volume
-v 卷名:容器内路径 # 具名挂载, mount type 为volume
-v /主机路径:/容器路径 # 指定路径挂载,mount type为bind, 在docker volume ls中不会出现
# 1. 匿名挂载(只有容器内的路径)
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看
docker volume --help
# 查看所有的数据卷
docker volume ls
"""
DRIVER VOLUME NAME
local 7f60ec2cd7ee435bf1758e6f145ef62419049115a8c4c12b073e409f1f97e8c4
local 493c55040d4b987d5b0e4e292274084b8b54bc279f5d0cf1d14cc1afffa44435
"""
这里就是匿名挂载
# 2. 具名挂载
docker run -d -P --name nginx01 -v mingzi:/etc/nginx nginx # mingzi为具名
# 查看
docker volume ls
"""
C:\Users\fanzone>docker volume ls
DRIVER VOLUME NAME
local 7f60ec2cd7ee435bf1758e6f145ef62419049115a8c4c12b073e409f1f97e8c4
local 493c55040d4b987d5b0e4e292274084b8b54bc279f5d0cf1d14cc1afffa44435
local 940f4aa52b7271864588fb1c53a8bb4447e42808b8e13175f06df90394737c42
local mingzi
"""
# 查看挂载详细位置
docker volume inspect mingzi
docker volume inspect 7f60ec2cd7ee435bf1758e6f145ef62419049115a8c4c12b073e409f1f97e8c4
"""
[
{
"CreatedAt": "2021-05-15T22:07:47+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mingzi/_data",
"Name": "mingzi",
"Options": null,
"Scope": "local"
}
]
"""
# 通过-v 容器内路径,加ro或rw改变读写权限
ro readonly # 只读
rw readwrite # 可读可写, 默认
docker run -d -P --name nginx01 -v mingzi:/etc/nginx:ro nginx
docker run -d -P --name nginx01 -v mingzi:/etc/nginx:rw nginx
注意:
- 所有的docker容器内的卷,没有指定目录的情况下都是在
/var/lib/docker/volumes/xxx/_data
- 通过具名挂载,可以方便找到一个卷,大多数情况使用具名挂载
方式二: 使用Dockerfile
dockerfile用于构建docker镜像的构建文件, 通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个命令,每个命令是一层
docker build -f Dockerfile -t fanhz/centos . # -f 指定Dockerfile文件, -t => --target
# Dockerfile,指令都是大写,每个命令就是镜像的一层
FROM centos
VOLUME ["volume01", "volume02"] # 这里是匿名挂载, 在容器内/volume01 和 /volume02
CMD echo "--------end ------ "
CMD /bin/bash
数据卷容器 ---- 多个容器间数据共享
# centos数据共享
docker run -it --name docker01 -v volumes fanhz/centos:1.0 # 此时docker01要挂载volumes目录,
docker run -it --name docker02 --volumes-from docker01 fanhz/centos:1.0 # docker01就叫数据卷容器
docker run -it --name docker03 --volumes-from docker02 fanhz/centos:1.0 # --volumes-from 数据卷容器 就可以实现数据间共享了,只能共享volumes目录
# 此时如果删除docker01, 则docker02和docker03中数据依然存在
docker rm -f docker01
两个mysql数据同步
# 多个mysql数据同步
docker run -d -P -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d -P -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
DockerFile
dockerfile用于构建docker镜像的构建文件
构建步骤:
- 编写dockerfile文件
- docker build 构建为一个镜像
- docker run 运行镜像
- docker push 发布镜像(dockerhub或阿里云镜像仓库)
Docker的构建过程
基础知识;
- 每一个指令必须为大写
- 执行从上向下执行
#
表示注释- 每一个指令都会创建一个新的镜像层,并提交
dockerfile是面向开发的,以后要发布项目,就编写镜像,编写dockerfile文件
步骤:
- Dockerfile: 构建文件,定义一切的步骤,源代码
- Dockerimages: 通过Dockerfile构建生成的镜像,最终发布和运行的产品
- Docker容器:容器就是镜像运行起来提供服务
指令说明
FROM # 基础镜像,从这里开始构建
MAINTAINER # 镜像是谁写的,一般姓名+邮箱
RUN # docker构建时候需要运行的命令
ADD # 添加文件,例如tomcat压缩包,可以自动解压(注意:填写路径时构建上下文)
WORKDIR # 容器启动后,直接到的工作目录,默认为根目录
VOLUME # 设置容器卷
EXPOSE # 指定暴露【端口】, EXPOSE指令实际上并不发布端口。它作为构建映像的人员和运行容器的人员之间的文档,通常发布端口在docker run 运行容器时指定-p来publish端口, 或者指定-P来publish所有指定端口。
CMD # 指定容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承Dockerfile这个时候会触发这个指令
COPY # 类似add,将文件拷贝到镜像中(注意:填写路径时构建上下文)
ENV # 构建时候设置环境变量
练习:安装centos
Docker hub中大多数的镜像都是FROM scratch
开始的
# 创建自己的centos
# Dockerfile文件内容- myDockerfile
"""
FROM centos
MAINTAINER fanhz<fanhang64@gmail.com>
ENV MYPATH /user/local
WORKDIR $MYPATH # 运行时候直接到的目录
RUN yum install -y vim
RUN yum install -y net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "___________end_______"
CMD /bin/bash
"""
# 构建镜像
docker build -f myDockerfile -t fanhz/centos:2.0 .
查看构建过程
docker history 镜像
CMD和ENTRYPOINT的区别
# CMD
""" my_cmd_test_dockerfile
FROM centos
CMD ["ls", "-a"]
"""
docker build -f my_cmd_test_dockerfile -t cmd_test:1.0 .
docker run cmd_test
# 想要追加命令,当你想要添加参数时候
docker run cmd_test -l
"""
error
"""
# 想要追加命令时候,-l 替换了cmd ['ls', '-a']
# 只能这样 docker run cmd_test ls -la
# ENTRYPOINT
"""
FROM centos
ENTRYPOINT ["ls", "-a"]
"""
# 可以直接在命令后面追加,不会替换
docker run entrypint_test -l
"""
ok
"""
练习Tomcat镜像
步骤:
-
准备tomcat压缩包和jdk压缩包
-
编写dockerfile文件,官方命名为
Dockerfile
,当build的时候回会自动找这个文件,不需要-f
指定。# Dockerfile FROM centos MAINTAINER fanhz<xxx@gmail.com> COPY readme.md /usr/local/readme.txt WORKDIR /usr/local ADD jdk-8u291-linux-x64.tar.gz /usr/local ADD apache-tomcat-7.0.109.tar.gz /usr/local RUN yum -y install vim ENV MY_PATH /usr/local WORKDIR $MY_PATH ENV JAVA_HOME /usr/local/jdk1.8.0_291 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-7.0.109 ENV CATALINA_BASH /usr/local/apache-tomcat-7.0.109 ENV PATH %PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-7.0.109/bin/startup.sh && tail -F /usr/local/apache-tomcat-7.0.109/bin/logs/catalina.out
-
构建镜像
docker build -t ffz:1.0 .
-
启动镜像
docker run -d -p 9090:8080 --name my_tomcat1 -v c:/Users/fanzone/Desktop/code/test_docker/test:/usr/local/apache-tomcat-7.0.109/webapps/test -v c:/Users/fanzone/Desktop/code/test_docker/logs:/usr/local/apache-tomcat-7.0.109/logs diytomcat
-
访问测试
-
发布项目(做了卷挂载,直接在本地test目录部署就行了)
发布自己镜像
1.发送到dockerhub
1. 登陆hub.docker.com
2. 在我们服务器上commit自己镜像
3. 登陆docker
docker login --help
docker login -u # 用户名
docker login -p # 密码
docker login 回车
4. 登陆成功之后可以提交镜像
docker push + 作者名/镜像名:版本号
# 报错 An image does not exist locally with the tag: fanhz/hello-world
# 使用"docker tag"命令重命名镜像
docker tag 原来镜像id 新的镜像名+版本号
docker tag d1165f221234 fanhz/hello-world:1.0
5. push发布
docker push fanhz/hello-world:1.0
2. 发布到阿里云镜像
1. 登陆阿里云
2. 找到容器镜像服务
3. 创建命名空间
4. 创建容器镜像仓库
创建-》本地仓库
5. 浏览信息
docker logout # 退出登陆
docker login -u fxxx registry.cn-hangzhou.aliyuncs.com
docker push registry.cn-hangzhou.aliyuncs.com/my_test/my_test11:[镜像版本号]
Docker网络
docker0理解
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:7f:fc:3a:cb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:7fff:fefc:3acb/64 scope link
valid_lft forever preferred_lft forever
# linux可以ping通docker容器
原理:
-
每启动一个docker容器,docker就会为容器分配一个ip,veth-pair技术
-
在tomcat1中可以ping通tomcat2容器【容器和容器之间可以通信】
-
所有容器在不指定网络
--net
的情况下,都是docker0路由,docker会给我们的容器分配一个默认的可用ip。 -
docker中的所有网络接口都是虚拟的。
--link(不推荐)
# 不用通过地址,直接ping通
docker exec -it tomcat1 ping tomcat2
# 解决办法
docker run -d -P --name tomcat3 --link tomcat2 tomcat
docker exec -it tomcat3 ping tomcat2 # ping ok
docker exec -it tomcat2 ping tomcat3 # ping error
# 实例
--link=mysql_server:db # 是告诉当前容器需要使用mysql_server容器,并命名为db。这里db就是mysql_server容器的别名。在后面连接数据库的时候是可以直接使用mysql -h db -uroot -p1234来连接mysql数据库
docker network ls # 查看当前docker 可使用网络, 默认使用bridge 为docker0
docker network inspect 容器id # 查看网络信息
# 其实实质:tomcat3在 /etc/hosts 中配置tomcat02
docker exec -it tomcat3 cat /etc/hosts
"""
172.17.0.2 tomcat3 a7f47379aae4
"""
总结: --link
实质在tomcat3中的hosts添加tomcat2的虚拟ip,现在不建议使用--link
了。
现在使用自定义网络,不适用docker0(原因:不支持容器名连接)。
自定义网络(推荐 --net)
命令:
docker network ls # 查看当前网络
docker network rm id # 移除一个或多个网络
docker network inspect id # 展示一个网络的详细信息
docker network create ... # 创建一个网络
docker network connect 网络名 容器名 # 连接一个网络 (网络连通)
实例解释:
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
441c0f846b8f bridge bridge local
ecb7d6b80ad1 host host local
b45843327340 none null local
bridge: 桥接docker,默认
none: 不配置网络
host: 和宿主机共享网络
container: 容器网络连通,(用得少,局限大)
测试:(推荐使用 docker network create)
docker run -d -P --name tomcat01 --net bridge tomcat # 平时在直接执行docker run命令的时候,默认有--net bridge 参数
# 自定义网络,(创建网络)
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 my_net
"""
--driver bridge # 桥接,--driver参数写死
subnet 子网地址
gateway 网关
"""
# 创建两个my_net容器
docker run -d -P --name tomcat-net-01 --net my_net tomcat
docker run -d -P --name tomcat-net-02 --net my_net tomcat
# 可以【相互】ping通
docker exec -it tomcat-net-01 ping tomcat-net-02 # ping ok 反之ok
好处:
- redis和mysql集群,不同的集群对应不同的网络,互相隔离。
网络连通
问题: 比如mysql集群网络bridge(172.17.0.0/16) 而redis集群在另一个网络my_net(192.168.10.0),如何连通两个不同网段的容器。
# 解决办法 网络连通, 网卡和网卡不能连通,容器可以和my_net连通,就是在容器中又新增一个ip
docker network connet my_net tomcat01 # 之前的tomcat01网络在默认的bridge
# 连通之后就是将tomcat01添加到mynet网络中
docker network inspect mynet
"""
"Containers": {
"3f631dcfb8a7415a215afca9cf83df8e150687fcb47e5eca05d115145814c7de": {
"Name": "tomcat-net-01",
"EndpointID": "00345e1985cfac6ac0f759ea7d26eac90f32563b6d3bd1fab3cf98a70e1bab72",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"f50a8422bdc5a8f212e66c5ff026d52e8e19da7a3ceb2b4b56a1aabc677dbc70": {
"Name": "tomcat-net-02",
"EndpointID": "bf7194fdb79fb25e6e69de891f2ff588d6ac8e6c832e40c975b1a5c2aceedd4c",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"f549c3ae03262fb278fdd653b310ff41b509c1c7219ec8349db9c42edd460b81": {
"Name": "tomcat01",
"EndpointID": "3c5a7ce3ae7335b1e7b87f72340788b0c32d5ff6636aa9b73011c85b10a06beb",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
}
},
"""
实战:部署redis集群
实例:
# 创建网络
docker network create --dirver bridge --subnet 192.167.10.0/16 --gateway 192.16710.1 my_redis
# 生成redis的配置文件 redis.sh
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 192.167.10.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# 启动redis 从1-6
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 my_redis --ip 192.167.10.11 redis:5.0.9 redis-server /etc/redis/redis.conf
# 创建集群
docker exec -it redis-1 /bin/bash
redis-cli --cluster create 192.167.10.11:6379 192.167.10.12:6379 192.167.10.13:6379 192.167.10.14:6379 192.167.10.15:6379 192.167.10.16:6379 --cluster-replicas 1 # 然后yes
# 连接集群
redis-cli -c
# 设置键
set name zs # 假如写入redis-2
docker stop redis-2
get name # 切换到备用redis,高可用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通