【docker命令】

docker指令

    • 1、镜像和容器的关系
    • 2、Dockfile中特殊语法
      • (1) CMD 和 ENTRYPOINT
        • ① 普通案例
        • ② 特殊案例
          • a、dockfile中的命令 和 命令行中的命令有冲突
          • b、使用exec执行PID=1的命令
        • ③【cmd、entrypoint】和 exec 的关系
      • (2) ADD
    • 3、镜像命令
      • (1)镜像生成
        • 【方案一】: 指定dockerfile,生成镜像
        • 【方案二】:容器备份,生成镜像
      • (2)拉取镜像
      • (3)镜像查看
      • (4)删除所有未被任何容器引用的镜像 【危险!不建议】
      • (5)push镜像到docker hug
    • 4、容器命令
      • (1)创建并启动容器
        • ① 常用参数
        • ② -v 参数
        • ③ 命令行参数
      • (2)容器查看
      • (3)进入容器 docker exec
        • ① docker exec 的含义
        • ② 和Dockfile的执行命令【cmd/entrypoint exec xx】的区别
      • (4)退出容器
      • (5)容器的主进程(PID=1的进程)
      • (6)关闭、启动、重启容器
      • (7)删除容器
      • (8)容器备份和恢复
        • ① 备份容器生成新镜像
        • ② 保存镜像到本地文件
        • ③ 把镜像拷贝到无网络的电脑,然后通过docker加载镜像
      • (9)容器启动日志
    • 5、容器通信(待验证)

Docker学不会?不妨看看这篇文章 (qq.com)
Docker批量删除REPOSITORY、TAG为none的镜像_shenzhen_zsw的专栏-CSDN博客_docker删除repository
docker删除镜像的时候报错–image has dependent child images - 清风软件测试 - 博客园

1、镜像和容器的关系

镜像是一个静态的只读模板,它包含了运行一个应用程序所需要的所有东西,包括代码、运行时环境、库、环境变量和配置文件。
容器是镜像nginx的一个运行实例(如果把镜像看做类,容器就是类的实例对象)。

2、Dockfile中特殊语法

(1) CMD 和 ENTRYPOINT

ENTRYPOINT 和 CMD 都是 Dockerfile 的语法.

(1) CMD 用于提供默认的容器启动命令。如果在启动容器时没有提供命令,那么将使用 CMD指定的命令。如果在启动容器时提供了额外命令,那么 CMD 指定的命令将被忽略。
(2) ENTRYPOINT 用于将容器当作一个可执行程序。ENTRYPOINT指定的命令将总是在容器启动时执行,而且不会被忽略。如果在启动容器时提供了命令,那么这个命令将作为 ENTRYPOINT 命令的参数。

① 普通案例

假设你有一个 Dockerfile,其中包含以下指令:

 ENTRYPOINT ["echo"] 
 CMD ["Hello, Docker!"]

当你基于这个 Dockerfile 构建镜像,并用这个镜像启动容器时,如果你没有提供命令,那么容器将输出 “Hello, Docker!”。
这是因为 ENTRYPOINT 指定的 echo 命令将使用 CMD 指定的 “Hello, Docker!” 作为参数。
如果你在启动容器时提供了命令,例如 docker exec -it <容器ID或names> “Hello, World!”,那么容器将输出 “Hello, World!”。这是因为你提供的命令将作为 ENTRYPOINT 指定的 echo 命令的参数,而 CMD 指定的 “Hello, Docker!” 将被忽略。

② 特殊案例

a、dockfile中的命令 和 命令行中的命令有冲突

如果Dockerfile中指定 ENTRYPOINT ["sh", "xx.sh"], 但是又运行了 “docker run --name 容器名 -idt /bin/bash ”, 这时 Docker 将尝试运行 sh xx.sh /bin/bash。这意味着 /bin/bash 会被作为参数传递给 xx.sh 脚本。
如果你想在容器启动时运行 /bin/bash 而不是 sh xx.sh,你需要在 docker run 命令中使用 --entrypoint 参数来覆盖 Dockerfile 中的 ENTRYPOINT 指令,如下所示:

docker run --name 容器名 -idt --entrypoint /bin/bash 
b、使用exec执行PID=1的命令

在 Dockerfile 中,可以使用 exec 形式的 ENTRYPOINT 或 CMD,例如:

ENTRYPOINT ["exec", "python", "app.py"]
或
CMD ["exec", "python", "app.py"]
这里的 exec 实际上并不是指 exec 命令,而是表示 Docker 应该使用 exec 形式来执行指定的命令,而不是使用 shell 形式。

在 exec 形式中,Docker 会直接执行指定的命令,而不是通过 /bin/sh -c(command) 或其他 shell 来执行。这样做的一个好处是,执行的命令会成为容器的 PID 1 进程,这样它就可以接收到系统的各种信号,例如 SIGTERM。
即无exec时,docker默认会转化为 /bin/sh -c [cmd或entrypoint] python app.py;有exec时docker会直接执行 [cmd或entrypoint] python app.py,不再借助shell执行。

③【cmd、entrypoint】和 exec 的关系

  • dockfile中的 exec 是在标识一种命令执行形式。告诉机器直接以PID=1来运行后面的命令,而不是先启动shell
    再在shell里执行后续命令。

  • cmd、entrypoint 是在标识 后面的命令是 默认值 or 必须执行的值。

    所以两者是独立的,只是可以组合一起用罢了。cmd exec python app.py 并不能保障PID=1的命令就是python app.py,因为cmd的命令会被 “docker run xx 命令”中的命令取代,而exec只保障后续执行的命令一定是PID=1,至于具体的命令是什么还要受cmd、entrypoint、docker run xx 的指令限制。

(2) ADD

ADD命令用于将主机中的文件或目录复制到镜像中,所以基于同一个镜像启动的所有容器都会有相同的工作目录。复制完成后,主机目录和镜像目录是完全独立的,后续操作都不会互相影响。

例如 ADD ./pythonwork/test01 /test会将主机上的./pythonwork/test01目录下的所有内容复制到镜像下的/test目录下。

3、镜像命令

(1)镜像生成

【方案一】: 指定dockerfile,生成镜像

docker build -t <镜像名:镜像tag> -f= .
  • -t 参数:用于指定镜像。如果不写-t,Docker 会为构建的新镜像分配一个随机的哈希值作为其 ID,但其镜像名:镜像tag=None:None,会导致删除、引用等管理上的问题。如果只是tag如果不写,默认是lastest。
  • 最后的点(.):表示 Dockerfile 所在的上下文目录的路径,点(.)即当前目录,也可以指定其他目录。Docker
    构建过程需要一个上下文。上下文是在本地的文件系统中指定的一个目录,它包含了构建镜像所需要的所有文件。

注意:这个目录会影响Dockerfile中的ADD、COPY指令,因为这两个指令中对应的本地文件系统目录就是以该目录为父目录的。举例:

如果 Dockerfile 和 app.py 在不同的文件夹下,那么你需要在执行 docker build 命令时,指定的构建上下文路径应包含这两个文件。

例如,你的文件结构如下:


/myproject/
|-- Dockerfile
/otherdir/
|-- app.py


你可以将 app.py复制或者移动到 myproject 目录下,这样 Dockerfile 和 app.py 就在同一个目录中了,然后你在 myproject
目录下执行 docker build 命令。


如果你不想移动 app.py 文件,那么你就需要选择一个包含 Dockerfile 和 app.py 的公共父目录作为构建上下文。
在这个例子中,公共目录可以选 / 目录,再在公共目录下执行 docker build 命令,并使用 -f 参数指定 Dockerfile 的路径,如下: docker build -t my-python-app:1.0 -f /myproject/Dockerfile .
然后在 Dockerfile 中,你可以使用以下命令将 app.py 文件添加到镜像中: ADD /otherdir/app.py /app/

请注意,这样会将 / 目录下的所有文件和子目录都包含到构建上下文中,这可能会使构建过程变得非常慢,并且可能会包含你不想添加到镜像中的文件。因此,通常建议将 Dockerfile 和所有需要添加到镜像的文件都放在同一个目录中。
所以常看到把Dockerfile和需要添加到镜像的文件都放在同一个目录下,然后再cd 到这个公共目录,执行docker build xx操作。

【方案二】:容器备份,生成镜像

docker commit -p <容器ID> 备份命名

(2)拉取镜像

docker image pull : 或者  docker pull :

其中:
PEPOSITORY-镜像的仓库源;TAG-镜像的标签。未指定TAG,默认是最新tag。
举例: docker image pull python

(3)镜像查看

 docker images

(4)删除所有未被任何容器引用的镜像 【危险!不建议】

多人协同下不建议使用!!!!

docker image prune -a

如果是要同时删除所有已经停止的容器以及所有未被任何容器引用的镜像,包括那些你可能希望保留的镜像:【同样危险!不建议!

docker system prune -a 

(5)push镜像到docker hug

推送镜像到 Docker Hub 需要以下步骤:

  • 首先,你需要在 Docker Hub 上创建一个账号。你可以在 https://hub.docker.com/ 上注册。
  • 在你的windows机器上安装docker desktop for
    windows.exe(linux上直接安装docker)。目前docker hub只支持push推动,不能在docker hub网站上直接上传本地文件。
  • 使用 docker login 命令登录到 Docker Hub:
    docker login
    
    输入你的 Docker Hub 用户名和密码后,你应该能看到一个“Login Succeeded”消息。
  • 【非必要】使用 docker tag 给镜像重命名,新名字包含你 Docker Hub的 用户名:
    docker tag 镜像名称:tag 用户名/镜像名称
    
  • 最后,使用 docker push 命令将镜像推送到 Docker Hub:
    docker push 用户名/镜像名称
    

完成这些步骤后,你的镜像就会出现在 Docker Hub 上的你的账号下,你可以在任何地方使用 docker pull 命令来下载和使用这个镜像。

4、容器命令

(1)创建并启动容器

① 常用参数

主命令:docker run xx
下面是一些常用的可选项:

(1)-d 或 --detach:在后台运行并且返回容器ID,也就是以分离模式运行容器。

(2)-i 或 --interactive:即使没有附加也保持STDIN(Standard
Input的缩写,即标准输入)打开,即以交互模式运行容器。

(3)-t 或 --tty:为容器分配一个虚拟终端,通常与 -i 一起使用。

(4)-p: 指定端口映射,格式为:[宿主机端口:
容器内web服务端口]。一般情况下,外部可通过【宿主机ip:宿主机port】访问容器内的web服务。

(5)-v:指定[宿主机硬盘地址: 容器目录]的映射卷。这样,就可以实现2个目录下的文件同步更新。

(6)-w:指定容器的工作目录

(7)–name: 指定容器的名字。

(8)–gpus:指定在容器内可以使用的主机GPU(如果你想在容器内使用GPU,那么必须至少指定–gpu参数)。如果你有4个GPU,编号为0,1,2,3,那么–gpus
‘“device=1,2”’,这样就只会分配编号为1和2的GPU给容器。–gpus all会分配全部的gpu。

(9)-e NVIDIA_VISIBLE_DEVICE:设置在容器内哪些GPU是可见的。如果你有4个GPU,编号为0,1,2,3,那么-e
NVIDIA_VISIBLE_DEVICES=2,3会让容器只能看到编号为2和3的GPU;all表示全部。

(10)【镜像名或id:tag】要放在所有参数的后面 如果本地不存在指定的镜像,Docker 会尝试从默认的 Docker
registry(例如 Docker Hub)下载该镜像。

备注:如果你想在容器内使用GPU,那么必须至少指定–gpu参数。至于是否需要指定-e NVIDIA_VISIBLE_DEVICES,则取决于你是否需要限制容器能够看到的GPU。如果不指定这个参数,邐默认情况下容器将能够看到所有的GPU。
而且,使用–gpus 和 -e NVIDIA_VISIBLE_DEVICE 需要你的Docker版本至少为19.03,并且安装了NVIDIA的Docker插件(nvidia-docker2或nvidia-container-runtime)。

【举例1】 docker run -d -p 8080:80 --name my_container nginx
在后台启动一个名为my_container的容器。由于容器my_container 是镜像nginx的一个运行实例,所以nginx服务也在后台被启动。-p表示将容器my_container 的80端口映射到宿主机的8080端口,这样你就可以通过访问宿主机的8080端口来访问这个容器里启动的nginx服务器。


【举例2】docker run -dit --name pythonFirst d92f72c38f7e /bin/bash
启用组合选项 -dit 可以启动一个可以交互的容器pythonFirst ,并且该容器在后台运行。这种模式对于需要长期运行,同时又需要人工交互的容器非常有用。例如,你可能需要运行一个web服务器并且需要通过shell进行配置。


【举例3】docker run --gpus all -p 8500:8500 -v /mnt/d/opencode/ChatGLM2-6B-main-docker:/cf/ -w /cf/ -dit --name openai_api -e NVIDIA_VISIBLE_DEVICE=all chatglm2:1 python3 openai_api.py
命令中使用了–gpus 和 -e NVIDIA_VISIBLE_DEVICE,表示当前容器openai_api内需要使用主机的gpu。-w表示容器的工作目录是/cf/(如果该文件夹在容器内不存在,则容器启动时会自动创建。首次创建时建议在目录名前后都加斜杠’/cf/‘,单斜杠’/cf’在首次创建时会默认其为文件格式,而不是目录格式)。

② -v 参数

WORKDIR 是 Dockerfile 的一个指令,用于设置后续指令运行时的工作目录。如果在 Dockerfile 中指定了 WORKDIR /app,那么后续的 RUN, CMD, ENTRYPOINT, COPY 和 ADD 指令都会在 /app 目录下执行。
当你运行一个 Docker 容器时:
(1)如果你没有使用 -v 选项指定主机和容器之间的目录映射,那么容器内的文件系统是完全独立的,你在容器内创建的文件不会影响到主机的文件系统。
(2)如果希望在主机和容器之间共享文件,你需要使用 -v 选项创建一个卷(volume),指定主机和容器之间的目录映射。
例如, docker run -it -v /host/dir: /container/dir, 会把主机上的 /host/dir 目录映射到容器的 /container/dir 目录。这样,你在容器的 /container/dir 目录中创建的文件会在主机的 /host/dir 目录中出现,反之亦然。
好处:如果你没有使用 -v 选项,容器内的文件系统会在容器停止和被删除时丢失。使用 -v 选项创建的卷,即使容器被删除,卷中的数据也会保留在主机上。

③ 命令行参数

    命令行运行参数:/bin/bash、/bin/sh等(bash是sh的超集,所以bash比sh功能更强大)

【举例】: docker run -dit --name pythonFirst d92f72c38f7e /bin/bash
这条命令中的 /bin/bash 是启动容器后要执行的命令。在这个例子中,/bin/bash 将在容器启动后运行,这样就会在容器中打开一个 bash shell。
如果你不提供这个命令,Docker将运行镜像中的默认命令。这个默认命令是在创建镜像时Dockfile中定义的。

(2)容器查看

1、查看正在运行的容器
以下命令效果一样:
(1)docker container ls
(2)docker ps

2、查看所有的容器
docker ps -a

3、查看指定容器
docker ps -f name=openai_api
-f: filter过滤

-f在同一条命令中可以重复多次使用,例如,查找container_name=openai_api且状态是exited的容器:
docker ps -a -f status=exited -f name=openai_api 

4、只查看容器的id信息
docker ps -q
-q:quiet静默输出container_id,常和容器名一起用:docker ps -q -f name=xx

(3)进入容器 docker exec

1、老的写法
docker exec -it <容器ID或names> /bin/bash

2、新的写法
docker container exec -it <容器ID或names> bash

两种都可以,看个人习惯。

至于/bin/bash 和 bash,两者都是用来启动 bash shell 的命令。他们的区别在于命令的路径。

(1)/bin/bash 是 bash 的绝对路径。这意味着系统会在 /bin 目录中查找 bash 程序。
(2)bash 是 bash 的相对路径。这意味着系统会在环境变量 $PATH 中指定的目录中查找 bash 程序。

在大多数情况下,/bin 目录都会被包含在 $PATH 中,所以 bash 和 /bin/bash 通常是等价的。但是在某些特殊的环境中,比如某些定制的 Docker 容器中,/bin 可能不在 $PATH 中,所以只能用 /bin/bash 来启动 bash。

① docker exec 的含义

当你在已经运行的容器中使用 docker exec 命令时,Docker 会在容器内启动一个新的 Shell(不是新的进程),然后再在这个新的 Shell 中执行docker exec 后面的命令。
需要明白的是,已经启动的容器其实就是一个虚拟终端,和任何一个纯净的主机终端都是一样的,可以在里面进行任何终端里可做的事情,而docker exec xx只是在这个虚拟终端里起一个shell而已。

② 和Dockfile的执行命令【cmd/entrypoint exec xx】的区别

而dockfile里的exec是在“标识”一种命令执行形式。告诉机器直接以PID=1来运行后面的命令,而不是先启动shell 再在shell里执行后续命令。

(4)退出容器

1、exit 或 ctrl+d:
    在 Unix 和类 Unix 系统中,ctrl+d 发送一个 EOF(End Of File)信号,表示输入结束。在一个交互式的 shell 中,输入 ctrl+d 会结束当前的 shell 会话。
    对于 Docker,如果你在一个运行中的 Docker 容器的交互式 shell 中输入 ctrl+d,那么你会结束这个 shell 会话并退出容器。
    如果这个容器是以交互式 shell 为【主进程】启动的,那么容器也会停止运行。
【备注:】容器的主进程,也就是执行容器启动时的命令行


2、ctrl+p+q:退出容器,但不关闭容器
     输入 ctrl+p+q 会让 Docker 在后台保持容器运行,而你可以返回到宿主机的 shell。这对于需要长时间运行的容器非常有用。

(5)容器的主进程(PID=1的进程)

如果生成镜像的Dockfile中包含CMD ["python", "xx.py"],同时你启动容器时使用了 docker run -it <镜像名称> /bin/bash,那么 /bin/bash 会成为容器的主进程,而 python xx.py 不会被执行。
如果你想要在容器启动时执行 python xx.py,同时也想要启动一个交互式的 bash shell,你可以在 docker run 命令中使用 -d 选项来让容器在后台运行,然后使用 docker exec 命令来启动一个新的 bash shell。例如:

docker run -d <镜像名称>
docker exec -it <容器ID或名称> /bin/bash

这样,python xx.py 会在容器的主进程中运行,而你也可以通过 docker exec 启动的 bash shell 来交互式地操作容器。

(6)关闭、启动、重启容器

docker stop <容器ID>

docker start<容器ID>

docker restart<容器ID>

(7)删除容器

删除前要确保容器已经关闭。

1、删除单个容器
 docker rm  <容器ID>

2、需要删除所有容器,加上$(docker ps -a -q)
 docker rm $(docker ps -a -q)

3、删除所有已经停止的容器
 docker container prune -a

rm 和 --rm:

docker rm 和 docker --rm 是两个用于不同场景的命令,它们的功能和用途都不一样:
(1)docker rm:
这是一个命令,用于删除一个或多个已经停止运行的 Docker 容器。你需要提供你想要删除的容器的 ID 或者名字。例如 docker rm container_id 会删除 ID 为 container_id 的容器。
(2)docker run --rm:
–rm 是 docker run 命令的一个选项,它的作用是在容器停止后自动删除容器。例如 docker run --rm -it ubuntu bash 会运行一个 Ubuntu 容器,等到你退出容器后,Docker 会自动删除这个容器。

(8)容器备份和恢复

① 备份容器生成新镜像

docker commit -p <容器ID> 备份命名

注意:此操作虽然是对容器的备份,但是生成的是一个新镜像,而不是容器。

② 保存镜像到本地文件

docker save -o 文件名称及路径 镜像名称
或
docker save  镜像名称  >  文件名称及路径

举例:docker save chenge_docker_backup > d:\chenge_docker_backup.tar

两种命令的差异:

(1)docker save -o 文件名称及路径 镜像名称 使用的是 Docker 命令自带的 -o(–output)选项来指定输出文件。
(2)docker save 镜像名称 > 文件名称及路径 使用的是 shell 的输出重定向操作符(>)来指定输出文件。
在大多数情况下,你可以选择任何一种方式来保存 Docker 镜像。但是如果你在一个不支持 shell
输出重定向操作符的环境中(比如某些简化版的 shell 或脚本语言中),你可能只能使用 -o 选项来保存镜像。

③ 把镜像拷贝到无网络的电脑,然后通过docker加载镜像

 docker load -i 文件名称及路径

(9)容器启动日志

```
docker logs <容器名>
```

5、容器通信(待验证)

由于Docker容器是独立的环境,它不会共享主机的环境或者包。如果我在docker所在的主机上安装了mysql、nginx,docker容器默认是无法使用的。
但对于mysql和nginx这种服务类的软件,通常我们会为它们单独创建Docker容器,然后通过Docker的网络功能,使得这些容器之间可以互相通信。

以下是为MySQL和Nginx创建Docker容器并通过Docker的网络功能使它们可以互相通信的步骤:

① 安装Docker:首先需要在你的服务器上安装Docker。


② 拉取MySQL和Nginx的Docker镜像: docker pull
mysql:5.7 docker pull nginx


③ 创建Docker网络: docker network create mynetwork
这个命令创建了一个名为"mynetwork"的网络。


④ 运行MySQL容器: docker run --name mymysql -e
MYSQL_ROOT_PASSWORD=my-secret-pw --network=mynetwork -d mysql:5.7
这个命令创建了一个名为"mymysql"的容器,将它连接到了"mynetwork"网络,并设置了MySQL的root密码。


⑤ 运行Nginx容器: docker run --name mynginx --network=mynetwork -d nginx

这个命令创建了一个名为"mynginx"的容器,将它连接到了"mynetwork"网络。
通过以上步骤,你已经创建了MySQL和Nginx的Docker容器,并且它们都在同一个网络"mynetwork"中,因此它们可以互相通信。
需要注意的是,你可能需要根据你的实际情况,如MySQL的配置、Nginx的配置,以及你的应用需求,来修改上述命令。

你可能感兴趣的:(docker,docker)