最近写了一个Telegram Bot,它可以使用语音和文字与GPT进行交互,成为了我日常重度使用的工具。从练习英语的听说读,到日常的搜索使用上都让我有了不少收获。终于,日常跑在我笔记本上的日子就要过去了,我需要它能日常跑在我的服务器上,所以准备使用Docker整个image,使得我日常的更新和服务器的迁移更为简单些。所以写下这个小纸条,方便以后自己回来查看。
安装Docker
使用Homebrew安装简单方便:
brew install --cask docker
Homebrew会视你的机器安装Intel或Arm版本的Docker。然后让我们启动Docker
open /Applications/Docker.app
一路Next之类,这就安装好了。记得在你的配置中配置好Docker的虚拟机所使用的资源:
最后,点右上角的Sign in登录到你的dockerhub上。
本地编译image
准备好你的Dockerfile,以下是我常使用的一个为Python项目准备的Dockerfile
FROM python:latest
RUN apt-get update && apt upgrade -y
RUN cd /
COPY . /bot/
RUN cd bot
WORKDIR /bot
RUN pip install -r requirements.txt
CMD [ "python", "bot.py" ,"-c","/conf"]
在Dockerfile所在的文件夹中,打开终端,并构建Docker镜像。在终端中执行以下命令:
docker build -t edgebot .
这将使用名为“bot”的标记构建一个Docker镜像。注意,“.”代表当前目录,因此Docker将在当前目录中查找Dockerfile文件并使用它来构建镜像。此过程可能需要几分钟,具体取决于您的计算机性能和您的网络速度。
当编译好之后,你就可以在本机的镜像列表中看到edgebot了
docker image ls
运行你的image
从image运行
一但在docker镜像列表中看到你编译好的image,你就可以运行它了,接下来让我们尝试运行。你可以发现在Dockerfile中我们运行这个程序时有一个参数-c
,它指定了一个配置文件的目录,我们希望运行镜像时的配置文件都从这个目录中来取得。在容器里,它的路径是/conf
,在你的Host里,我希望它被mount指向当前目录下的conf
目录。
docker run -v "$(pwd)/conf:/conf" edgebot
其中,-v
参数用于挂载卷。$(pwd)
返回当前目录的完整路径,因此 $(pwd)/conf
将是当前目录下的 conf 目录的完整路径。edgebot
是要运行的 Docker 镜像的名称。
使用这个命令,Docker 将运行指定的镜像,并将容器内的 /conf
目录映射到当前目录下的 conf
目录。这意味着您可以在当前目录下编辑配置文件,并且它们将在容器内部可见。
有时我们会遇到程序运行时出现问题,我们希望进入容器查看环境,这样就需要运行容器并起动容器内的shell了。
docker run -it -v "$(pwd)/conf:/conf" edgebot /bin/bash
其中,-it
参数用于分配一个伪终端并启用交互模式,edgebot
是要运行的 Docker 镜像的名称,/bin/bash
是要运行的 shell。
使用这个命令,Docker 将启动指定的镜像并进入容器的 shell。您现在可以在 shell 中执行命令并与容器交互。要退出 shell 并停止容器,请使用 exit
命令。
查看容器列表
一但你运行一个镜像后,Docker就会在本机自动创建一个容器。如果我们运行了上面两个命令,哪么我们可以使用以下命令查看
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7521819b97ba edgebot "python edge.py -c /…" 6 minutes ago Exited (0) 5 minutes ago vigorous_chaplygin
fe3e828f24bd edgebot "python edge.py -c /…" 6 minutes ago Exited (0) 6 minutes ago focused_driscoll
docker ps
将显示所有容器的列表,包括正在运行的容器和已经停止的容器,同样包括容器的 ID、镜像名称、状态、端口映射、创建时间等信息。如果没有-a
参数,将只会显示正在运行的容器。
运行容器
要运行指定的容器,可以使用以下命令:
docker start <container_id_or_name>
其中,<container_id_or_name> 是要启动的容器的 ID 或名称。
使用这个命令,Docker 将启动指定的容器并使其处于运行状态。注意,如果容器已经在运行中,则此命令不会产生任何效果。
如果要同时进入已经在运行的容器的 shell,可以使用以下命令:
docker exec -it <container_id_or_name> /bin/bash
其中,-it 参数用于分配一个伪终端并启用交互模式,<container_id_or_name> 是要进入的容器的 ID 或名称,/bin/bash 是要运行的 shell。
使用这个命令,Docker 将进入指定的容器并进入容器的 shell。您现在可以在 shell 中执行命令并与容器交互。要退出 shell,请使用 exit
命令。
容器管理
容器名称管理
要修改容器的名称,可以使用以下命令:
docker rename <old_name> <new_name>
其中,<old_name> 是原始的容器名称,<new_name> 是要修改的新容器名称。
使用这个命令,Docker 将重命名指定的容器。请注意,容器名称必须是唯一的。
如果要查看已命名的容器的列表,可以运行以下命令:
docker ps --format "table {{.ID}}\t{{.Names}}"
这将显示当前计算机上所有容器的 ID 和名称列表。您可以在该列表中查找容器的名称并使用上述 docker rename
命令将其重命名。同样也可以加入-a
参数也列出没有在运行的容器。
首次运行镜像时指定容器名称
如果要在运行镜像时指定容器的名称,可以使用以下命令:
docker run --name <container_name> <image_name>
其中,--name 参数用于指定容器的名称,<container_name> 是您要为容器指定的名称,<image_name> 是要运行的 Docker 镜像的名称。
使用这个命令,Docker 将启动指定的镜像,并使用指定的容器名称创建一个新容器。如果未指定容器名称,则 Docker 将自动生成一个随机的容器名称。
注意,容器名称必须是唯一的。如果您尝试为已经存在的容器分配一个重复的名称,则会收到一个错误消息。为了避免这种情况,请在创建容器时始终指定唯一的名称。
发布镜像
一般我们会要构建并将一个 Docker 镜像推送到 Docker Hub 上,可以按照以下步骤进行操作:
在本地计算机上构建 Docker 镜像:
docker build -t <username>/<image_name>:<tag> .
其中,<username> 是您的 Docker Hub 用户名,<image_name> 是您要构建的镜像名称,<tag> 是您要为镜像指定的标签(例如版本号)。
.
表示使用当前目录中的 Dockerfile 构建镜像。运行以下命令以验证构建的镜像已经创建:
docker images
这将显示本地计算机上的所有 Docker 镜像列表,包括刚刚构建的镜像。
使用以下命令将镜像推送到 Docker Hub:
docker push <username>/<image_name>:<tag>
其中,<username> 是您的 Docker Hub 用户名,<image_name> 是您要推送的镜像名称,<tag> 是您要推送的标签。
注意,您需要先登录到 Docker Hub 才能将镜像推送到您的账户。您也可以使用以下命令登录:
docker login
运行这个命令后,您需要输入您的 Docker Hub 用户名和密码。
使用以下命令检查您刚刚推送的镜像是否已经上传到 Docker Hub:
docker search <image_name>
这将显示 Docker Hub 上所有具有指定名称的镜像列表。如果您可以看到您刚刚推送的镜像,则表示您已成功将镜像推送到 Docker Hub。
清除容器和镜像
要清除不使用的 Docker 镜像和容器,可以使用以下命令:
清除所有停止的容器:
docker container prune
这将删除所有已停止的容器,这些容器不会影响任何运行中的应用程序。
清除所有未使用的镜像和悬空的构建缓存:
docker image prune -a
这将删除所有未被任何容器使用的镜像以及悬空的构建缓存。
清除所有未使用的卷:
docker volume prune
这将删除所有未被任何容器使用的卷。
注意:在执行这些命令之前,请确保您已经备份了需要保留的数据。这些命令将清除您计算机上所有未使用的容器、镜像和卷。如果您不小心清除了某些内容,可能会导致数据丢失或不可恢复。
如果您想要清除指定的 Docker 容器和镜像,可以使用以下命令:
清除指定的容器:
docker rm <container_id>
其中,<container_id> 是您要删除的容器的 ID。您可以使用
docker ps -a
命令查看所有容器的 ID。如果要删除多个容器,请使用以下命令:
docker rm <container_id_1> <container_id_2> ...
清除指定的镜像:
docker rmi <image_id>
其中,<image_id> 是您要删除的镜像的 ID。您可以使用
docker images
命令查看所有镜像的 ID。如果要删除多个镜像,请使用以下命令:
docker rmi <image_id_1> <image_id_2> ...
支持不同平台
如果要同时支持ARM64和x64架构的Docker镜像,需要在构建Dockerfile时使用多架构支持(Multi-Architecture Support)功能。
- 在Dockerfile中包含适用于两个架构的指令和指令参数。
例如,下面是一个使用Alpine作为基础映像的Dockerfile示例,其中包括适用于ARM64和x64架构的指令:
# syntax = docker/dockerfile:1.2
FROM --platform=linux/amd64,linux/arm64/python:latest
WORKDIR /app
COPY . .
RUN apk add --no-cache gcc musl-dev
CMD ["./myapp"]
这个Dockerfile中的 --platform=linux/amd64,linux/arm64
参数指示Docker同时支持x64和ARM64架构。
- 构建Docker镜像
使用以下命令构建Docker镜像:
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest .
这个命令中的 --platform=linux/amd64,linux/arm64
参数告诉Docker同时构建x64和ARM64架构的镜像。
- 验证Docker镜像
可以使用以下命令验证Docker镜像是否同时支持ARM64和x64架构:
docker run --rm --platform=linux/amd64,linux/arm64 myimage:latest uname -m
这个命令将会在容器内运行 uname -m
命令并输出容器的架构,如果输出中同时包含 x86_64
和 aarch64
,则表示Docker镜像同时支持ARM64和x64架构。
通过使用多架构支持功能,可以轻松地在Docker容器中同时支持多种架构,并在需要时运行合适的容器。
运行docker buildx
时有可能你会看到如下的错误信息
ERROR: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
这个错误信息是因为Docker目前的默认构建驱动程序(docker driver)不支持多架构构建。
多架构构建(Multi-Architecture Support)是Docker的一个新功能,允许构建同时支持不同架构的Docker镜像,例如x86_64、ARM64等。
要使用多架构构建功能,需要使用Buildx驱动程序,而不是默认的Docker驱动程序。Buildx是一个构建工具,它可以在Docker中同时构建多个架构的镜像,并且可以在不同的构建平台上运行。
要解决这个错误,需要使用Buildx驱动程序。可以按照以下步骤来使用Buildx:
- 安装Buildx插件
docker buildx install
- 创建一个Buildx构建器
docker buildx create --name mybuilder
- 切换到Buildx构建器
docker buildx use mybuilder
- 构建Docker镜像
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest .
这些命令中的 --platform=linux/amd64,linux/arm64
参数告诉Buildx同时构建x64和ARM64架构的镜像。
通过使用Buildx构建器,可以轻松地构建同时支持多种架构的Docker镜像,并在需要时运行合适的容器。