docker基本使用

Docker从17.03版本之后分为CE和EE两个版本。

(Community Edition,社区版),EE(Enterprise Edition,企业版),一般使用社区版。

首先,需要了解docker的几个概念:

  1. 镜像(Image):Docker 镜像(Image),就相当于是一个root文件系统。比如官方镜像ubuntu:16.04就包含了完整的一套Ubuntu16.04最小系统的root文件系统。

  2. 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

  3. 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

简单来说,Docker镜像是用于创建Docker容器的模板,容器是独立运行的一个或一组应用,是镜像运行时的实例。如果不理解的话,可以类比虚拟机。镜像就好像是虚拟机快照文件,通过同一个快照文件,可以复制成很多个不同的虚拟机(容器)。

镜像使用

关于镜像的常用命令有4个:

  1. docker search:搜索镜像;
  2. docker build:从Dockerfile或者「上下文(PATHURL)」中构建镜像;
  3. docker images:查看已经构建的镜像列表;
  4. docker pull:从docker存储库中拉取镜像到本地;
  5. docker rmi:删除已经构建好的镜像;

1.1 搜索镜像 (docker search)

当不确定需要pull的镜像的全称时,可以先使用docker search来查询镜像列表,然后再选取想要的镜像来pull。

docker search [options] <某个XXX镜像名字>  # 搜索镜像,一般在dockerhub网站中搜索
docker pull <某个XXX镜像名字>  # 下载镜像

运行命令可以参考:

docker run -itd -p 8080:80 --name my-nginx nginx
# -d,--detach:以后台模式运行容器,并返回容器ID;
# -t,--tty:为容器分配一个伪终端;
# -i,--interactive,以交互模式运行容器,并保持终端激活;
## 一般创建的docker容器都需要使用 -d ,除非你想创建一个前台运行的容器,操作完成后就想让它停止;
## 如果在 docker run -it 不使用 -d 那么启动容器后如果你使用 ctrl+c 或 exit 退出交互模式,docker容器会停止运行
## -it 一般会同时使用。

# -p 选项用于将容器的80端口映射到宿主机的8080端口;
# --name 选项用于指定容器的名称为my-nginx;
# 最后的 nginx 是要运行的镜像的名称。

示例:

以下面的pikachu靶场为例:

docker run -itd -p 8888:80 --name pikachu area39/pikachu

此时再执行docker ps -a,这时会新开一个pikachu容器,PORT为3306/tcp, 0.0.0.0:8888->80/tcp, :::8888->80/tcp。在物理主机访问http://虚拟机IP:8080,成功访问靶场。

1.2 构建镜像 (docker build)

该命令从Dockerfile和「上下文」构建Docker镜像。

构建的上下文是位于指定PATHURL。构建过程可以引用上下文中的任何文件。例如,您的构建可以使用COPY指令来引用上下文中的文件。

docker build [OPTIONS] PATH|URL|-

[OPTIONS]:
 #1. --tag/-t:名称和可选的“名称:标签”格式的标签

URL:
 #1. 引用Git存储库
 #2. 引用预打包的tarball上下文
 #3. 引用纯文本文件

示例:

docker build -t folive .
 # 此示例指定当前目录"."为PATH,
 # 因此本地目录中的所有文件都发送到 Docker 守护进程。

1.3 查看镜像列表 (docker images)

docker images [OPTIONS] [REPOSITORY[:TAG]]

[OPTIONS]:
 #1. --all/-a: 显示所有图像(默认隐藏中间图像)
 #2. --filter/-f: 根据提供的条件过滤输出

1.4 拉取镜像 (docker pull)

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

[OPTIONS]:
#  1. --all-tags/-a:下载存储库中的所有标记图像

1.5 删除镜像 (docker rmi)

docker rmi [OPTIONS] IMAGE [IMAGE...]

[OPTIONS]:
 #1. --force/-f: 强制删除图像
 #     如果使用该 -f 标志并指定图像的短ID或长ID,
 #     则此命令将取消tag并删除与指定ID匹配的所有镜像。

可以使用镜像的短ID或长ID、tag或摘要来删除镜像。如果图像有一个或多个引用它的tag,必须在删除图像之前删除所有这些tag。当镜像被tag删除时,摘要引用会自动删除。

容器使用

关于镜像的常用命令有4个:

  1. docker run:初始化一个容器,将镜像放到容器中;
  2. docker ps:查看容器列表(类比ls);
  3. docker start/restart:启动/重启一个容器;
  4. docker stop:停止一个正在运行的容器;
  5. docker rm:删除一个容器;
  6. docker exec/attach:临时进入一个容器(命令行);
  7. docker logs:查看某个容器的日志;
  8. docker inspect:查看Docker底层日志;

初始化容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

IMAGE # 指定要运行的镜像

[OPTIONS]:
 #_1. --detach/-d:让容器在后台运行。
 #_2. --publish-all/-P: 将所有暴露的端口发布到随机端口。
 #_3. --publish/-p:是容器内部端口绑定到指定的主机端口, 
 #      如 docker run -d -p [主机端口]:[容器端口] [IMAGE]
 #_4. --hostname/-h: 容器主机名,访问域名或ip
 #_5. --name: 自定义容器名字,需唯一
 #_6. --restart: 容器退出时应用的重启策略,默认值为 no
 #_7. --volume/-v:绑定挂载卷,即目录映射:[主机目录]:[容器内目录],
 #      把容器的数据保存到主机,防止容器突然停止或被删除数据丢失
 #_8. --rm: 容器退出时自动移除
 #_9. --interactive/-i: 交互式操作,即使没有连接,也保持 STDIN 打开。
 #10. --tty/-t: 终端,分配一个伪 TTY。

示例1

docker run -it ubuntu /bin/bash

# ubuntu: ubuntu 镜像。
# /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

若是docker中的服务与服务器本地服务段端口发生冲突(例如本地和docker同时开启了mysql服务),则可修改docker服务的端口映射

查看容器

docker ps [OPTIONS]

[OPTIONS]:
 #1. --all/-a:显示所有容器(默认显示刚刚运行)
 #2. --filter/-f "conditions": 根据提供的条件过滤输出,可通过容器名称or容器端口号等条件过滤
 #3. --quiet/-q:仅显示容器 ID
 #4. --size/-s: 显示总文件大小,每个容器显示两个不同的磁盘大小,
 #     size(virtual size),size是用于每个容器的可写层的数据量(在磁盘上),
 #     virtual size: 容器使用的只读镜像数据加上容器的可写层所使用的数据量size,
 #     两个容器间的镜像数据可能是共享的。

示例1:--filter

# 匹配名称中包含该`name=nostalgic`字符串的所有容器
docker ps --filter "name=nostalgic"

# 匹配所有发布端口为 80 的容器
docker ps --filter publish=80

# 输出条件介绍:
 # CONTAINER ID: 容器ID。
 # IMAGE: 使用的镜像。
 # COMMAND: 启动容器时运行的命令。
 # CREATED: 容器的创建时间。
 # STATUS: 容器状态。状态有7种:
   # 1. created(已创建)
   # 2. restarting(重启中)
   # 3. running(运行中)
   # 4. removing(迁移中)
   # 5. paused(暂停)
   # 6. exited(停止)
   # 7. dead(死亡)
 # PORTS: 容器的端口信息和使用的连接类型 (tcp\udp)
 # NAMES: 自动分配/自定义的容器名称。

容器的启停、删除

2.3.1 启动已停止运行的容器 (docker start)

docker start CONTAINER_ID/CONTAINER_NAME
docker restart CONTAINER_ID/CONTAINER_NAME

2.3.2 停止运行的容器 (docker start)

docker stop CONTAINER_ID/CONTAINER_NAME

2.3.1 删除容器 (docker rm)

docker rm [OPTIONS] CONTAINER_ID/CONTAINER_NAME

[OPTIONS]:
 #1. --force/-f: 强制删除正在运行的容器 (使用SIGKILL)

进入容器

在使用-d参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

  1. exec(推荐):推荐大家使用docker exec命令,用此命令退出容器终端,不会导致容器的停止。
  2. attach:如果从这个容器退出,会导致容器的停止。

2.4.1 attach

docker attach [OPTIONS] CONTAINER

2.4.2 exec

docker exec [OPTIONS] [CONTAINER_ID/CONTAINER_NAME] COMMAND [ARG...]

[OPTIONS]:
 #1. --detach/-d:分离模式:后台运行命令
 #2. --interactive/-i:交互式操作,即使没有连接,也保持STDIN打开
 #3. --tty/-t:终端,分配一个伪TTY

示例:

docker exec -it [容器ID] /bin/bash

查看日志

2.5.1 查看容器日志 (docker logs)

docker logs [OPTIONS] CONTAINER

[OPTIONS]:
 #1. --follow/-f:跟踪日志输出
 #2. --since:显示某个开始时间的所有日志
 #3. --time/-t:显示时间戳
 #4. --tail:仅列出最新N条容器日志

示例:logs

跟踪查看容器mynginx的日志输出。

runoob@runoob:~$ docker logs -f mynginx
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
2016/07/10 16:53:33 [error] 5#5: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.239.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.239.130", referrer: "http://192.168.239.130/"
192.168.239.1 - - [10/Jul/2016:16:53:33 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.239.130/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
192.168.239.1 - - [10/Jul/2016:16:53:59 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36" "-"
...

查看容器mynginx从2016年7月1日后的最新10条日志。

docker logs --since="2016-07-01" --tail=10 mynginx

获取docker容器交互式命令行

2.5.2 检查WEB应用程序 (docker inspect)

查看Docker的底层信息, 它会返回一个JSON文件记录着Docker容器的配置和状态信息,如ip地址,mac地址,镜像名称,日志路径,端口映射等。

docker inspect [OPTIONS] CONTAINER_ID/CONTAINER_NAME

[OPTIONS]:
# --format/-f: 使用给定的Go模板格式化输出

示例:inspect

# 获取IP地址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_ID

# 获取mac地址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' $INSTANCE_ID

# 获取日志路径
docker inspect --format='{{.LogPath}}' $INSTANCE_ID

# 获取镜像名称
docker inspect --format='{{.Config.Image}}' $INSTANCE_ID

# 获取所有端口映射
docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' $INSTANCE_ID

宿主机与容器交互

文件操作

3.1.1 文件复制 (cp)

docker cp /path/to/host/file.txt <container_name_or_id>:/path/to/container/file.txt

3.1.2 文件挂载


容器操作(容器移动)

在Docker中,移动容器通常指的是将容器从一个主机迁移到另一个主机。以下是一些常见的方法:

使用Docker的导出和导入功能

导出容器:可以使用docker export命令将运行中的容器导出为一个tar包。

docker export -o container.tar <container_id>

导入容器:将导出的tar包传输到目标主机后,使用docker import命令将其导入为一个新的镜像。

docker import container.tar <image_name>:<tag>

运行容器:导入后,使用docker run命令启动容器。

docker run -d --name <new_container_name> <image_name>:<tag>
  1. 优点:简单易用,不需要额外工具。
  2. 缺点:不保留容器的运行状态(如内存状态、网络配置等),只保存文件系统。

使用Docker镜像

基于容器创建镜像:可以使用docker commit命令将运行中的容器创建为一个新的镜像。

docker commit <container_id> <new_image_name>:<tag>

推送镜像到仓库:将创建的镜像推送到Docker Hub或其他私有镜像仓库。

docker push <new_image_name>:<tag>

在目标主机拉取镜像:在目标主机上从仓库拉取镜像。

docker pull <new_image_name>:<tag>

运行容器:使用docker run命令启动容器。

docker run -d --name <new_container_name> <new_image_name>:<tag>
  1. 优点:可以保留容器的文件系统和部分配置。
  2. 缺点:不保留容器的运行状态(如内存、网络等)。

使用CRIU(Checkpoint/Restore in Userspace)

常见操作场景

删除镜像步骤

在容器是启动的情况下,我是先把容器停掉,删除容器,最后再是删除镜像。

停掉启动容器->删除容器->删除镜像

  • 停掉启动容器:docker stop <容器id>
  • 删除容器:docker rm <容器id>
  • 删除镜像:docker rmi <镜像id>

若通过docker rm <容器id>命令删除报错,可尝试使用docker rmi -f强制删除镜像

通过yml配置文件拉取docker镜像

以vulhub fastjson/1.2.24-rce靶场为例:

cd fastjson/1.2.24-rce
docker-compose build
docker-compose up -d  # -d 为“以后台的方式运行容器”

失陷容器应急处理

确认容器失陷后,一般我们可以采取暂停容器、隔离容器甚至杀死容器的方式来做紧急处理。

  1. 使用docker pause,暂停容器中所有的进程。

  2. 使用docker commit,用于将被入侵的容器来构建镜像,从而保留现场痕迹,以便溯源。

  3. 将正在运行的Docker容器禁用网络。

    # 将运行中的容器与用户定义的网桥断开连接
    [root@localhost ~]#docker network disconnect bridge <container-name>
    _
    # 禁用veth
    [root@localhost ~]#docker exec -it <container-name> cat /sys/class/net/eth0/iflink
    29
    [root@localhost ~]#ip link show |grep 29
    29: vethbf5239e@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue masteefault 
    [root@localhost ~]# ip link set vethbf5239e down
    
  4. 使用docker kill杀掉运行中的容器(谨慎操作!!!)

    docker kill -s KILL <container-name>
    

没有vi/vim/nano,如何操作文档

# 删除最后一行
sed -i '$d' [FILEPATH]
# 往文件中写一行
echo "Hello, world!" >> [FILEPATH]

实战案例

搭建一个python环境,

方法一:直接pull镜像

Docker Hub上提供了官方的Python镜像,你可以根据需要选择合适的版本。

  1. 拉取最新版本的 Python 镜像:

    # 拉取 Python 镜像
    docker pull python:latest
    # 如果你需要特定版本的 Python(例如 Python 3.9),可以指定版本号:
    docker pull python:3.9
    
  2. 启动Python容器:你可以通过以下命令启动一个 Python 容器,并进入交互模式:

    docker run -it python:latest /bin/bash
    # -it        参数表示以交互模式运行容器。
    # /bin/bash  是容器启动后执行的命令,用于进入Bash终端。
    

方法二:基于Dockerfile创建

如果你需要一个更定制化的 Python 环境(例如安装特定的库),可以创建一个Dockerfile。以下是一个简单的示例:

# Dockerfile1
# 基于官方 Python 镜像
FROM python:3.11.4-slim-bullseye

# 复制自定义的 hosts 文件
COPY hosts /etc/hosts

# 设置工作目录
WORKDIR /opt/app

# 设置环境参数
# 略

# 复制当前目录下的文件到工作目录
COPY . /opt/app/

# 安装 python 依赖
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 设置默认命令
ENTRYPOINT ["/bin/sh", "-c", "python main.py"]

/csmpProbeCheck文件树如下:

csmpProbeCheck
 +-- log/
 +-- conf.py
 +-- flowProbeCheck.py
 +-- keepAlive.py
 +-- main.py
 +-- requirements.txt
 +-- TOKEN.txt
 \-- toolkits.py

requirements.txt

pandas==2.1.4
requests==2.31.0

构建和运行Docker容器:

在包含Dockerfile的目录下,运行以下命令构建镜像:

docker build -t <image-name> <context-path>
docker build -t csmp-probe-check .
# -t 参数用于指定镜像的名称(例如 csmp-probe-check )。

其他注意事项

  1. 数据持久化:如果需要持久化数据(例如代码文件或数据库),可以使用Docker卷:

    docker run -v $(pwd)/var/csmpProbeCheck:/var/csmpProbeCheck -it python:latest /bin/bash
    

    这会将当前目录下的/csmpProbeCheck文件夹挂载到容器的/var/csmpProbeCheck目录。

  2. 如何查看docker配置文件(daemon.json)的默认路径?

    dockerd --help
    

    在输出中,你会看到--config-file参数,它指定了Docker配置文件的路径。默认情况下,Docker 使用/etc/docker/daemon.json文件。

    Daemon configuration file (default "")

方法三:Dockerfile+挂载宿主机文件

编写Dockerfile

# 基于官方 Python 镜像
FROM python:3.11.4-slim-bullseye

# 创建一个目录,用于挂载宿主机的文件夹
RUN mkdir -p /opt/app

# 设置工作目录
WORKDIR /opt/app

# 复制当前目录下的 requirements.txt 文件到工作目录
COPY ./requirements.txt /opt/app/

# 安装 python 依赖
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 设置默认命令
ENTRYPOINT ["/bin/sh", "-c", "python main.py"]

# 或者使用一个占位命令,确保容器启动后不会立即退出
# CMD ["tail", "-f", "/dev/null"]

生成docker镜像

根据Dockerfile,通过docker build生成镜像:

docker build -t csmp-app .

docker容器初始化

通过docker run将镜像投放到容器中(初始化):

Docker 的守护模式(Daemon Mode)和交互模式(Interactive Mode)是运行容器的两种不同方式,它们的主要区别在于容器的运行方式和用户与容器的交互方式。

  • 守护模式(Daemon Mode)的容器在后台运行,不会占用当前终端。适合运行长期运行的服务(如Web服务器、数据库等)。容器的标准输入(stdin)被关闭,用户无法直接与容器交互。容器的标准输出(stdout)和标准错误(stderr)通常被重定向到日志文件或 Docker 的日志系统中。
  • 交互模式(Interactive Mode)的容器在前台运行,会占用当前终端。适合需要用户交互的场景(如开发环境、调试工具等)。容器的标准输入(stdin)保持打开状态,用户可以通过终端直接与容器交互。容器的标准输出(stdout)和标准错误(stderr)直接显示在终端上。
  1. 守护模式(Daemon Mod)初始化:

    docker run -d -p 8000:8000 --name my-container \
        -v /path/to/host/folder:/app \
        my-app
    # --detach/-d:以守护模式运行容器;
    # --port/-p 8000:8000:将容器的8000端口映射到宿主机的8000端口;
    # --name my-container:为容器指定一个名称;
    # -v /path/to/host/folder:/app:将宿主机的"/path/to/host/folder"挂载到容器的"/app"目录中;
    # my-app:使用之前构建的镜像。
    
    ## 示例:
    docker run -d -p 8000:8000 --name csmp-app \
        -v /var/csmpProbeCheck:/opt/app \
        csmp-app
    

    文件挂载注意事项:

    1. 权限问题:确保宿主机的文件夹路径/path/to/host/folder对Docker守护进程是可访问的,并且具有适当的权限。
    2. 用户和组ID:如果宿主机和容器内的用户和组ID不一致,可能会导致权限问题。可以通过在 Dockerfile中设置用户和组来解决。
    3. 挂载路径:挂载路径在宿主机和容器中必须一致,且容器内的路径必须在镜像中已经存在。通过这种方式,你可以将宿主机的文件夹挂载到容器中,方便在容器中访问和操作宿主机的文件。
  2. 交互模式(Interactive Mode)初始化:

    docker run -it --name my-container my-image
    # -i:表示交互式,保持标准输入(stdin)打开
    # -t:分配一个伪终端
    
    ## 示例:
    docker run -it --name csmp-app csmp-app
    

进入已经启动的容器

docker exec -it [CONTAINER_ID] /bin/bash
# 如果没有启动,可以使用 docker start [CONTAINER_ID/CONTAINER_NAME] 来启动容器

# 进行一些手动操作,例如向 hosts 中写入一行
echo "172.16.10.20 csmp.qaxc-inc.cn" >> /etc/hosts

*[可选]手动挂载宿主机文件夹

docker run --mount type=bind, source=[/path/to/host/folder],destination=[/app] \
    [OPTIONS] IMAGES_NAME


docker run -d --name csmp-probe-check \
    --mount type=bind,source=/var/csmpProbeCheck,destination=/opt/app \
    csmp-app

docker run -d --name csmp-probe-check \
    --mount type=bind,source=/var/csmpProbeCheck,destination=/opt/csmpProbeCheck \
    csmp-app

退出docker容器

  1. 在交互模式下,可以通过输入exit或按Ctrl+D退出容器,容器将停止运行。
  2. 如果你只是想暂时离开容器而不退出,可以按Ctrl+P然后立刻按下Ctrl+Q组合键。容器将继续在后台运行,终端将返回到宿主机。

容器、镜像的铲除

  1. 使用docker ps查看正在运行的容器,并使用docker stop [CONTAINER_ID]停止相关容器;
  2. 使用docker ps -a全面检查相关容器,然后使用docker rm [CONTAINER_ID]删除相关容器;
  3. 使用docker images查看本地镜像列表,然后使用docker rmi [IMAGES_ID]删除相关镜像;

报错排障

报错docker-compose API版本过低

[centos@CentOS]../fastjson/1.2.47-rce❯ docker-compose up -d
ERROR: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version

可以试试下面的办法:

如果你使用Docker 1.13以上版本,需要将docker-compose.yml中的version:'2'修改为version: '2.1'也就是这里的version。然后再docker-compose up -d试试。

报错,连接超时

$ docker pull python:latest

Error response from daemon: Get "https://registry-1.docker.io/v2/ ": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

编辑配置文件daemon.json文件,配置镜像加速地址,文件内容如下:

{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://hub-mirror.c.163.com"
  ]
}

重启 Docker 服务:

sudo systemctl daemon-reload
sudo systemctl restart docker
posted @ 2025-08-03 12:06  _Mytt  阅读(34)  评论(0)    收藏  举报