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 的不同,又分为两种情况:

  1. host_dir 使用绝对路径时,表示将宿主机的当前目录挂载到容器内对应目录。目录内的文件将以宿主机为主。

    1. 如果宿主机没有当前目录,会自动创建。目录存在则不对目录做任何修改。
    2. 在宿主机内修改目录内的文件会同步修改到容器内;反之在容器内修改也会同步到宿主机内。
    3. 这种方式挂载的目录存在一个问题:如果挂载的是项目的配置目录,比如nginx的配置目录 /etc/nginx ,宿主机对应挂载目录必须已经存在必要的文件,否则容器会因为缺少必要的配置文件而无法启动。
    4. 如果是挂载的文件,则该文件在挂载时必须已经存在,否则会报错。而且挂载的文件在宿主机修改后,不会同步到容器对应文件。所以不建议挂载文件。
  2. host_dir 使用卷名/文件夹名。这种方式挂载的目录,将以容器内对应目录的内容为主。容器内该目录有啥,则宿主机该目录内就有啥,且同步修改。

    1. 可以认为卷名就是文件夹名,宿主机的卷固定存放在 /var/lib/docker/volumes/卷名container_dir 内的文件内容会同步 /var/lib/docker/volumes/卷名/_data
    2. 如果在创建容器时,该卷不存在,会自动创建,并填充容器内对应目录内的所有文件。可以使用已经存在的卷用于挂载到新的容器。如果使用的是已经存在的卷进行挂载,则不会主动将容器内对应目录的文件覆盖到宿主机的卷内,即不会对现有卷做任何操作。
    3. 删除容器时,不会删除卷。
    4. 可以使用 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的网络,容器之间互相访问不需要再经过宿主机。即

  1. 若有两个nginx容器,分别由宿主机的801和802代理。原本它们互相访问应该通过 宿主机ip:801宿主机ip:802 进行。
  2. 在有了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主从复制集群。

github bitnami/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的差异存储。

posted @ 2024-08-13 16:01  azsd  阅读(69)  评论(0)    收藏  举报