Docker基础操作
学习记录 留作参考
祝君好运
参考内容:
Docker 命令大全 | 菜鸟教程 (runoob.com)
尚硅谷3小时速通Docker教程,雷神带练docker部署到实战!_哔哩哔哩_bilibili
Docker - 快速通关 (3h) (yuque.com)
docker 常用命令
docker run
docker run imageName
最简单的创建并启动一个容器的命令。启动之后会一直挂在前台。需要增加更多参数来进行配置镜像启动。
docker run -d --name myName -p 81:80 -v host_dir:container_dir imageName
创建并启动一个容器:
-d 采用进程守护方式——容器启动后会在后台继续运行。
--name myName 指定容器的名称,否则docker会生成一个随机的容器名。
-p 81:80 指定端口映射:将宿主机的81端口映射到容器的80端口。
-v host_dir:container_dir 将宿主机的一个目录挂载到容器的一个目录上,就可以实现内部文件的同步。后面有详细讲。
docker ps
docker ps
展示当前运行着的容器
docker ps -a
展示所有容器(包含已经停止的容器)
docker start
docker start 容器id
docker start 容器名
启动一个容器
docker stop
docker stop 容器id
docker stop 容器名
停止一个容器
容器打包成镜像并分享
这种可以是修改容器的部分代码,然后打包成一个新的tar包,解压到其他机器上再运行。
提交:docker commit
docker commit -m '提交备注' myContainer newImage:1.0.0
将现有的容器重新打包成一个新的镜像
myContainer 现有的容器,可以是容器名称,也可以是容器id
newImage:1.0.0 新镜像的名称和版本号,其中版本号可选
保存:docker save
上一步使用docker commit 之后,就可以通过 docker images 查看到刚刚提交的image镜像了。
docker save -o abc.tar newImage:1.0.0
使用 docker save 可以将刚刚生成的镜像打包输出到指定的tar文件内,方便传递。
docker save -o abc.tar sha256编号
除了通过镜像名称进行打包之外,还可以使用commit得到的 sha256 编码来进行输出。
加载:docker load
通过加载上一步得到的 abc.tar 就可以得到刚刚打包的镜像(可以用来在新机器上部署)
docker load -i abc.tar
-i abc.tar 带加载的tar包文件路径
这样会解压成一个新的镜像,完成后可以通过 docker images 就可以查看到新的镜像
新的镜像仍旧通过 docker run -d --name xxx -p 80:80 image_name 来创建并运行容器
docker 发布镜像
登录docker账号,并将打包号的镜像发布到docker仓库。 -- 2024.7之后docker官网就一直打不开了,这部分仅作学习。
登录:docker login
首先到官网注册docker账号。然后在命令行输入 docker login 进行登录。
命名:docker tag
使用 docker tag 命令来给新打包的镜像起一个新的名字,按照docker的规则,待发布到仓库的镜像名称都是 用户名/镜像名 。
docker tag local-img:v1.0 username/new-img-name:v1.0
将本地名为 local-img ,且版本号为 v1.0 的镜像重新命名(创建别名)为 username/new-img-name 版本号为 v1.0
本操作过后,使用docker images 可以查看到以上的两个镜像,镜像名不同,但是他们的镜像id相同
推送:docker push
可以使用该命令,将指定的镜像推到docker hub。
需要注意的是指定标签和latest标签是独立的,需要分两次提交。
docker push username/new-img-name:v1.0
推送指定标签的镜像
docker push username/new-img-name
推送默认标签(latest)的镜像
docker 目录挂载、卷挂载
容器的文件系统,精简了很多命令,所以直接进入容器内修改文件会变得非常不方便。如果修改了容器内的文件,并且删除了该容器,那么下次再使用相同命令创建容器时,所得到的容器与之前的容器是不一致的。
因此docker提供了挂载文件系统的功能,可以进行文件和目录的挂载,来新增和修改容器中的文件(在挂载文件时会有问题,此处描述以挂载目录为准)。当创建容器时使用了挂载目录,之后又对挂载目录内的文件进行了修改,等下次再使用同样命令创建容器时,所得到的容器与之前的容器是一致的。
方法:在 docker run -v host_dir:container_dir 来挂载目录
其中,container_dir 必须是容器内的绝对路径。根据 host_dir 的不同,又分为两种情况:
-
host_dir使用绝对路径时,表示将宿主机的当前目录挂载到容器内对应目录。目录内的文件将以宿主机为主。- 如果宿主机没有当前目录,会自动创建。目录存在则不对目录做任何修改。
- 在宿主机内修改目录内的文件会同步修改到容器内;反之在容器内修改也会同步到宿主机内。
- 这种方式挂载的目录存在一个问题:如果挂载的是项目的配置目录,比如nginx的配置目录
/etc/nginx,宿主机对应挂载目录必须已经存在必要的文件,否则容器会因为缺少必要的配置文件而无法启动。 - 如果是挂载的文件,则该文件在挂载时必须已经存在,否则会报错。而且挂载的文件在宿主机修改后,不会同步到容器对应文件。所以不建议挂载文件。
-
host_dir使用卷名/文件夹名。这种方式挂载的目录,将以容器内对应目录的内容为主。容器内该目录有啥,则宿主机该目录内就有啥,且同步修改。- 可以认为卷名就是文件夹名,宿主机的卷固定存放在
/var/lib/docker/volumes/卷名。container_dir内的文件内容会同步/var/lib/docker/volumes/卷名/_data。 - 如果在创建容器时,该卷不存在,会自动创建,并填充容器内对应目录内的所有文件。可以使用已经存在的卷用于挂载到新的容器。如果使用的是已经存在的卷进行挂载,则不会主动将容器内对应目录的文件覆盖到宿主机的卷内,即不会对现有卷做任何操作。
- 删除容器时,不会删除卷。
- 可以使用
docker volume ls查看docker内的所有卷,使用docker volume inspect 卷名查看指定卷的信息,使用docker volume rm 卷名删除指定卷。
- 可以认为卷名就是文件夹名,宿主机的卷固定存放在
docker volume
docker对卷的操作
docker volume ls
列出docker所有的卷
docker volume inspect 卷名
查看指定卷的信息
docker volume rm 卷名1 <卷名2>
删除指定的卷
docker网络
安装docker后,会自动在本机创建一个名为 docker0 的网络,可以使用 ip a 具体查看,其ip地址为: 172.17.0.1 。
ip+端口号
借助docker的网络,容器之间互相访问不需要再经过宿主机。即
- 若有两个nginx容器,分别由宿主机的801和802代理。原本它们互相访问应该通过
宿主机ip:801和宿主机ip:802进行。 - 在有了docker0的网络之后,docker会为每个容器分配一个IP,具体可以通过
docker container inspect 容器名(或者docker inspect 容器名)来查看容器的ip。这样上面两个nginx容器,就可以通过容器的docker0ip:80来互相访问。
使用 ip + 端口号 来配置容器间互相访问可能会存在一些问题,比如容器重启之后,ip就会发生变化,导致原ip失效,或者访问到别的容器。因此docker提供了另一种解决方案,即域名。
域名
docker支持创建多个网络,在同一网络内,可以将容器名作为该容器在本网络下的域名进行访问。同时也可以正常的使用 域名+端口号。
容器的重启不影响域名的使用。
docker network ls
列出docker内所有网络
docker network create <网络名>
创建一个新的docker网络,docker会为其分配新的网段。
docker network rm <网络名>
删除指定网络。如果还有容器使用该网络,则不能删除。
具体使用域名的操作:
docker network create mynet
创建docker网络 mynet
docker network ls
可以查看到刚刚创建的网络
docker run -d --name app1 -p 801:80 --network mynet nginx
使用nginx镜像创建app1容器,配置宿主机801端口代理容器80端口,容器加入mynet网络
docker run -d --name app2 -p 802:80 --network mynet nginx
使用nginx镜像创建app2容器,配置宿主机802端口代理容器80端口,容器加入mynet网络
docker exec -it app1 bash
采用交互的方式登录app1容器内
app1容器内:curl http://app2
在app1容器内,通过docker网络,使用域名访问app2容器的80端口。
实操1:redis主从复制
综合上面学习的知识,使用 bitnami 发布的 redis 镜像(比redis官方镜像配置更简单),在单机搭建redis主从复制集群。
# 首先创建docker网络: mynet
docker network create mynet
# 在宿主机创建两个用于保存redis持久化存储的目录
# 如果仅测试,可以省略这一步,并且把下面 docker run 的 -v 一行删掉即可。
# -p 参数表示递归的创建文件夹
# -m 777 表示 rd1、rd2 文件夹,所有人都拥有最大权限
mkdir -p -m 777 /data/bitnami/redis/rd1
mkdir -p -m 777 /data/bitnami/redis/rd1
# 创建redis主机实例,加入mynet网络,容器名为redis01,使用宿主机的8001端口代理容器的6379端口,密码为123456
# -v 表示将宿主机的一个目录挂载到容器内对应目录,用于保存持久化内容。容器内对应目录的位置可以在bitnami的线上文档中查询到
docker run -d -p 8001:6379 --network mynet --name redis01 \
-v /data/bitnami/redis/rd1:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=master \
-e REDIS_PASSWORD=123456 \
bitnami/redis:latest
# 创建redis从机实例,加入mynet网络,容器名为redis02,使用宿主机的8002端口代理容器的6379端口。
# -v 表示将宿主机的一个目录挂载到容器内对应目录,用于保存持久化内容。容器内对应目录的位置可以在bitnami的线上文档中查询到
# 配置主机的地址为redis01,端口为6379,主机密码为123456。从机的密码为1234567
docker run -d -p 8002:6379 --name redis02 --network mynet \
-v /data/bitnami/redis/rd2:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=slave \
-e REDIS_MASTER_HOST=redis01 \
-e REDIS_MASTER_PORT_NUMBER=6379 \
-e REDIS_MASTER_PASSWORD=123456 \
-e REDIS_PASSWORD=1234567 \
bitnami/redis:latest
# 执行完上述命令之后,可以查看容器是否正常启动
docker ps
# 查看容器的日志,可以查看运行情况
docker logs 容器名
# 如果想要登录redis容器
docker exec -it docker容器名 redis-cli -a 密码
# 测试完成后,停止并删除相关容器及文件
docker stop redis01 redis02
docker rm redis01 redis02
docker network rm mynet
rm -rf /data/bitnami/
docker 复制文件
在使用Docker容器时,有时需要在容器和宿主机之间复制文件。Docker提供了docker cp命令,允许用户从容器复制文件到宿主机,或者反过来。这个命令非常实用,尤其是当创建容器时没有挂载宿主机目录,导致无法直接在宿主机与容器之间共享文件时。
使用docker cp命令要从容器复制文件到宿主机,可以使用以下命令格式:
docker cp <容器名或ID>:<容器内文件路径> <宿主机目标路径>
例如,如果要将名为nginx-web的容器中的/home/licence.txt文件复制到宿主机的/home目录下,可以执行:
docker cp nginx-web:/home/licence.txt /home
同样地,如果要将宿主机的文件复制到容器中,命令格式稍有不同:
docker cp <宿主机文件路径> <容器名或ID>:<容器目标路径>
例如,将宿主机的/home/licence.txt文件复制到nginx-web容器的/home目录下,可以执行:
docker cp /home/licence.txt nginx-web:/home
注意事项
- docker cp命令不受容器是否启动的影响,无论容器是运行状态还是停止状态,都可以执行文件复制操作。
- 在执行docker cp命令时,需要确保指定的路径正确无误,以避免复制失败或者文件被复制到错误的位置。
- 通过这些简单的命令,就可以在Docker容器和宿主机之间轻松地复制文件,无需复杂的配置或者额外的文件共享设置。这使得在开发和部署过程中的文件传输变得更加灵活和便捷。
其他
docker采用分层存储。容器启动后,镜像的内容是只读的,用户对容器内部的修改,会记录在镜像外面的读写层。当使用一个镜像运行多个容器时,各自容器只有修改的那部分内容属于自己,其他的都是镜像内公用的。所以,当使用同一个镜像运行多个容器,并不会增加多少磁盘占用。同时,当使用镜像A自己制作一个新的镜像B时,多占用的内容也仅仅是新镜像B修改的部分。参照Git的差异存储。
浙公网安备 33010602011771号