Docker - 新手向导

博文目录


docker入门,这一篇就够了。

新手向导 (Get Started)

官方文档 Get Started

本向导中的试验部分需要一台Linux主机, 可以是云服务器, 也可以是虚拟机, 需安装 Docker 环境

应用程序容器化

本节里, 我们会容器化一个简单的 Web Node.js 应用 Todo, 它的主要功能就是管理一些要做的事项, 可以添加/删除事项, 可以标记事项已完成. 这个示例并不需要我们熟悉 Node.js 和 JavaScript, 仅仅是展示下构建镜像运行镜像的流程

下载应用代码

如果Linux服务器上安装了Git, 那可以直接运行 git clone https://github.com/docker/getting-started.git 克隆项目代码, 也可以在Windows上克隆代码, 再通过FTP工具传到服务器

容器化该应用

要构建镜像, 需要使用 Dockerfile, 这是一个文本文件, 没有扩展名

通过 cd getting-started/app 进入 app 目录, 目录中有 package.json 和 spec 与 src 两个目录, 通过 touch Dockerfile 新建一个 Dockerfile, 使用 vim 或 文本编辑器 把下面的内容写入到 Dockerfile 中

# syntax=docker/dockerfile:1
   
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

然后通过 docker build -t getting-started . 命令构建镜像

docker build 命令使用Dockerfile来构建一个新的镜像。你可能已经注意到Docker下载了很多“层”。这是因为您指示生成器要从 node:18-alpine 节点开始。但是,由于你的机器上没有,Docker会自动下载这些镜像。

Docker下载镜像后,Dockerfile中的指令会复制到您的应用程序中,并使用yarn安装应用程序的依赖项。CMD指令指定从此映像启动容器时要运行的默认命令。

最后,-t 选项用于标记您的镜像。可以简单地认为是指定最终镜像的名称。由于您在开始时命名了该镜像,因此在运行容器时可以引用该镜像。

这个 `.` 在docker构建命令的末尾,告诉docker它应该在当前目录中查找Dockerfile。

构建成功后, 执行 docker images 即可看到该镜像

REPOSITORY        TAG       IMAGE ID       CREATED       SIZE
getting-started   latest    ed1ef9e8de78   About a minute ago   265MB
配置镜像加速器

运行构建命令很有可能会失败, 大概率是网络问题, 可以配置一下国内的镜像加速器, 建议多配几家, 我一开始只配了个阿里的, 结果构建直报错, 后来又加了腾讯的和其他的, 这才最终成功, 但中途也失败了几次, 所以, 构建失败可以多执行几次, 有概率成功

阿里云 Docker 镜像加速器

当你下载安装的 Docker 版本不低于1.10时,建议直接通过daemon config进行配置。使用配置文件 /etc/docker/daemon.json(没有时新建该文件),然后通过 systemctl restart docker 重启 Docker 即可

{
  "registry-mirrors": ["https://whvuvvy4.mirror.aliyuncs.com"]
}

启动这个应用容器

镜像已经构建好了, 通过 docker run -dp 3000:3000 --name getting-started getting-started:1.0.0 命令来创建并启动该镜像的一个容器, -d 是指定容器在后台运行, -p 用来绑定服务器端口和容器内端口的映射关系, 如果没有绑定这个端口印射, 我们没有办法访问容器内的应用程序

执行 docker ps 就可以看到正在运行的容器了

在浏览器打开 http://localhost:3000 就可以看到我们的 “Todo” 应用了

在这里插入图片描述
在这里插入图片描述

更新应用程序

本节我们修改一些应用的代码, 然后将其重新构建为镜像, 并重新运行容器

修改 src/static/js/app.js 中第56行的 No items yet! Add one above!You have no todo items yet! Add one above!

使用 docker build -t getting-started 命令来重新构建该镜像的新版本

REPOSITORY        TAG       IMAGE ID       CREATED       SIZE
getting-started   latest    b5a67802db59   About a minute ago   265MB
<none>            <none>    ed1ef9e8de78   15 minutes ago       265MB

使用 docker run -dp 3000:3000 --name getting-started getting-started:1.1.0 来启动新容器, 结果会报错, 新容器无法启动, 因为旧容器运行时占用了主机的3000端口, 只有停止旧容器才可以运行新容器

可以使用 docker ps 查看容器 ID, 使用 docker stop <the-container-id> 停止容器, 使用 docker rm <the-container-id> 删除容器, 也可以使用 docker rm -f <the-container-id> 直接停止并删除容器

再次使用 docker run -dp 3000:3000 --name getting-started getting-started:1.1.0 来启动新容器, 刷新浏览器可以看到文本内容已经变化

在这里插入图片描述

共享应用程序

要想共享镜像, 需要使用到镜像仓库, 默认的全球仓库是 Docker Hub

注册并登录 Docker Hub, 创建一个仓库, 名称使用 getting-started, 可见性选 Public, 我的该仓库推送镜像的命令是 docker push mrathena/getting-started:tagname, 其中 mrathena 是 Namespace, 也就是我的账号 ID, getting-started 是仓库名称, 一个仓库只能存同名镜像的不同版本

推送镜像

执行 docker push mrathena/getting-started 报本地不存在 Tag 为 mrathena/getting-started 的镜像, 我们得 tag 本地已有的镜像并为其命名

执行 docker login -u mrathena 在命令行里登录 Docker Hub

通过执行 docker tag getting-started mrathena/getting-started, 给 getting-started 镜像一个新的名字 mrathena/getting-started, 如果新名称后面不追加 :tagname 部分, 则默认是 latest

REPOSITORY                 TAG       IMAGE ID       CREATED          SIZE
getting-started            latest    b5a67802db59   15 minutes ago   265MB
mrathena/getting-started   latest    b5a67802db59   15 minutes ago   265MB
<none>                     <none>    ed1ef9e8de78   29 minutes ago   265MB

再次推送, 发现推送成功了

Play with Docker

我们在自己的主机上推送镜像, 速度慢的简直无法忍受, Docker 提供了一个免费的工具 Play with Docker , 我们可以使用该工具来做我们主机能做的所有事情, 该工具连接着真正的互联网, 网速非常快, 体验相当不错

使用镜像

在另一台装有 Docker 环境的主机上, 即可下载并启动刚刚推送的镜像, 使用 Play with Docker 来完成这个测试

浏览器打开 Play with Docker, 关联到我们的 Docker Hub 账户, 点击 Start, 再点击 ADD NEW INSTANCE, 开始使用真正的 Docker 环境

执行 docker run -dp 0.0.0.0:3000:3000 mrathena/getting-started 即可自动下载并运行一个新的容器

在这里插入图片描述
在这里插入图片描述

持久化数据库

前面的例子里, 当我们重启容器后, 先前添加的项目就全丢失了, 本节我们将深入了解容器是如何工作的

容器的文件系统

当容器运行时,它使用镜像中的各个层作为其文件系统。每个容器也有自己的“暂存空间”来创建/更新/删除文件。即使使用的是相同的镜像,在另一个容器中也看不到当前容器中的任何更改。

容器卷 (Container volumes)

卷提供了将容器的特定文件系统路径连接回主机的能力。就是把主机的某个路径印射了到容器中的某个路径, 在容器或主机中操作文件等同于在另一方操作文件。如果在容器重新启动时装载相同的目录,则会看到相同的文件。

保留所有数据

默认情况下,Todo 应用程序将其数据存储在容器文件系统中 /etc/todos/todo.db 的 SQLite 数据库中。我们只要创建一个卷将 /etc/todos 目录印射到主机的某个目录, 其内的 todo.db 就可以保存在主机的文件系统中, 这样重启容器数据也不会丢失

我们应该将卷装载视为不透明的数据桶。由Docker完全管理卷,包括磁盘上的存储位置。我们只需要记住卷的名称。

执行 docker volume create todo-db 创建了一个卷, 执行 docker rm -f <id> 删除正在运行的容器, 执行 docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started 启动 Todo 应用程序容器,添加 --mount 选项以指定卷装载。为卷指定一个名称,并将其装载到容器中的 ‘/etc/todos’,该容器将捕获在该路径上创建的所有文件。

执行 docker rm -f <id> 删除当前容器, 执行 docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started 创建并启动一个新的容器, 刷新浏览器, 之前添加的数据项应该没有丢失

深入卷

执行 docker volume inspect todo-db 即可查看卷的详细信息

[
    {
        "CreatedAt": "2023-06-19T14:19:01+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": null,
        "Scope": "local"
    }
]

也可以通过 docker inspect <id> 来查看容器信息, 其中 Mounts 不分就是装载的卷的信息

"Mounts": [
    {
        "Type": "volume",
        "Name": "todo-db",
        "Source": "/var/lib/docker/volumes/todo-db/_data",
        "Destination": "/etc/todos",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
],

使用绑定装载

在上节中, 我们使用了卷装载来将数据持久化到数据库中。当您需要一个持久的地方来存储应用程序数据时,卷装载是一个不错的选择。

绑定装载是另一种类型的装载,它允许您将主机文件系统中的目录共享到容器中。在处理应用程序时,可以使用绑定装载将源代码装载到容器中。保存文件后,容器会立即看到您对代码所做的更改。这意味着您可以在容器中运行进程来监视文件系统更改并对其作出响应。(感觉类似CI/CD的提交代码自动部署功能)

在本节中, 我们将使用绑定装载和名为nodemon的工具来监视文件更改,然后自动重新启动应用程序

快速卷类型比较

下表概述了卷装载和绑定装载之间的主要区别。除了卷装载和绑定装载外,Docker还支持其他装载类型和存储驱动程序,以处理更复杂、更专业的用例。要了解有关高级存储概念的更多信息,请参阅Docker中的 Manage data in Docker

Named volumesBind mounts
印射到主机的位置Docker 选择你决定
Mount 示例 (使用 --mount)type=volume,src=my-volume,target=/usr/local/datatype=bind,src=/path/to/data,target=/usr/local/data
Populates new volume with container contentsYesNo
支持卷驱动YesNo

尝试绑定装载

执行 cd getting-started/app

执行 docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash, Docker在容器文件系统的根目录中启动一个交互式bash会话。

在带有绑定挂载的ubuntu容器中启动bash, --mount 选项告诉Docker创建一个绑定挂载,其中src是主机上的当前工作目录getting-started/app,target是该目录应该出现在容器中的位置(/src)。

此时我们已经进入了容器, 执行 ls 可以查看容器的目录, 执行 cd src, 执行 ls, 发现 src 目录下内容与主机 getting-started/app 目录完全一致, 在容器内创建文件, 在主机也能看到, 两个路径已经印射起来了, 使用 Ctrl+D 快捷键可以退出容器的交互式会话

开发容器

在本地开发设置中,使用绑定挂载是很常见的。其优点是开发机器不需要安装所有的构建工具和环境。通过一个docker run命令,docker可以提取依赖项和工具。

这里用 getting-started 来演示实际开发过程中, 实时查看修改的内容

在开发容器中运行应用程序

以下步骤描述了如何使用执行以下操作的绑定装载来运行开发容器:

  • 将源代码装入容器
  • 安装所有依赖项
  • 启动 nodemon 以监视文件系统更改

通过以下步骤运行带有绑定装载的容器。

  • 确保没有 getting-started 容器在运行
  • 在 getting-started/app 目录运行以下命令
    docker run -dp 3000:3000 \
    -w /app --mount type=bind,src="$(pwd)",target=/app \
    node:18-alpine \
    sh -c "yarn install && yarn run dev"
    

以下是部分解释

  • -w /app, 设置“工作目录”或命令将从当前目录运行
  • –mount type=bind,src=“$(pwd)”,target=/app, 将当前目录从主机装入容器中的/app目录
  • node:18-alpine, 要使用的镜像。请注意,这是Dockerfile中应用程序的基本镜像
  • sh -c “yarn install && yarn run dev”, 使用sh(alpine没有bash)启动一个shell,运行yarn install来安装包,然后运行yarn run dev来启动开发服务器。如果您查看package.json内容,您将看到dev脚本启动nodemon。

执行 docker logs <container-id> 查看容器日志, 类似如下时, 说明好了

yarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 20.24s.
yarn run v1.22.19
$ nodemon src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000
使用开发容器开发应用程序

在主机上更新应用程序,并查看容器中反映的变化。

  • 在 src/static/js/app.js 文件的第109行,将“Add Item”按钮更改为简单的“Add”:
  • 刷新浏览器, 几乎实时变化, 而 Node Server 可能需要几秒钟的时间才能重新启动
  • 可以随意进行其他更改。每次进行更改并保存文件时,nodemon 进程都会自动重新启动容器中的应用程序。全部完成后,停止容器并执行 docker build -t getting-started . 可构建新镜像

多容器应用程序

通常,每个容器都应该只做一件事并做好它。即应用运行在一个容器中, 数据库运行在另一个容器中

在这里插入图片描述

容器网络

默认情况下,容器是孤立运行的,对同一台机器上的其他进程或容器一无所知。那么,如何允许一个容器与另一个容器进行通信呢?答案是建立网络。如果你把两个容器放在同一个网络上,它们可以相互通信。

启动 MySQL

在网络上放置容器有两种方法:

  • 启动容器时分配网络。
  • 将已运行的容器连接到网络。

在以下步骤中,我们将首先创建网络,然后在启动时附加MySQL容器。

执行 docker network create todo-app 创建一个网络

执行如下命令, 启动一个 MySQL 容器并将其连接到网络。我们还将定义一些环境变量,数据库将使用这些变量来初始化数据库。要了解有关MySQL环境变量的更多信息,参考 MySQL Docker Hub listing 列表中的“Environment Variables”部分。

docker run -d \
     --network todo-app --network-alias mysql \
     -v todo-mysql-data:/var/lib/mysql \
     -e MYSQL_ROOT_PASSWORD=secret \
     -e MYSQL_DATABASE=todos \
     mysql:8.0

在上面的命令中,有一个名为 todo-mysql-data 的卷,它安装在 /var/lib/mysql 中,这是MySQL存储数据的地方。但是,我们从未运行过 docker volume create 命令。Docker识别出您]我们想要使用一个命名卷,并自动创建了一个。

通过 --network 指定使用 todo-app 网络, 通过 --network-alias 给该容器在 todo-app 网络中起了个别名(hostname)为 mysql, 即其他容器连接到该网络后, 使用 mysql 这个 hostname 即可访问该容器

若要确认数据库已启动并运行,需要连接到数据库来确认

docker exec -it <mysql-container-id> mysql -u root -p

出现密码提示时,键入 secret, 执行 SHOW DATABASES;, 执行 exit 退出容器, 至此, MySQL 容器就好了

连接到 MySQL

每个容器都有自己的IP地址。

为了更好地理解容器网络,我们先用一用 nicolaka/netshoot 容器,该容器附带了许多工具,这些工具对解决或调试网络问题非常有用。

执行 docker run -it --network todo-app nicolaka/netshoot 下载并启用该容器, 确保该容器和 MySQL 容器在同一个网络上

在该容器中,我们将使用 dig 命令,这是一个有用的DNS工具。您将查找主机名mysql的IP地址。

执行 dig mysql 得到如下的响应

; <<>> DiG 9.16.22 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6853
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mysql.				IN	A

;; ANSWER SECTION:
mysql.			600	IN	A	172.18.0.2

;; Query time: 1 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Mon Jun 19 07:45:21 UTC 2023
;; MSG SIZE  rcvd: 44

在“ANSWER SECTION (应答部分)”中,我们看到mysql的一条A记录,解析为172.18.0.2(您的IP地址很可能有不同的值)。虽然mysql通常不是一个有效的主机名,但Docker能够将其解析为具有该网络别名的容器的IP地址。我们之前使用了 --network-alias。

这意味着你的应用程序只需要连接到一个名为 mysql 的主机,它就会与数据库对话。

使用 MySQL 运行应用程序

Todo 应用程序支持设置一些环境变量来指定MySQL连接设置。它们是:

  • MYSQL_HOST: 运行 MySQL Server 的主机的 hostname
  • MYSQL_USER: 用户名
  • MYSQL_PASSWORD: 密码
  • MYSQL_DB: 数据库名

在 getting-started/app 路径下执行如下命令

docker run -dp 3000:3000 \
   -w /app -v "$(pwd):/app" \
   --network todo-app \
   -e MYSQL_HOST=mysql \
   -e MYSQL_USER=root \
   -e MYSQL_PASSWORD=secret \
   -e MYSQL_DB=todos \
   node:18-alpine \
   sh -c "yarn install && yarn run dev"

执行 docker logs <container-id> 查看容器的日志,会看到类似于下面的消息,这表明它正在使用mysql数据库。

yarn install v1.22.19
[1/4] Resolving packages...
success Already up-to-date.
Done in 0.41s.
yarn run v1.22.19
$ nodemon src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
Waiting for mysql:3306.
Connected!
Connected to mysql db at host mysql
Listening on port 3000

刷新浏览器, 并添加一些新的项目

执行 docker exec -it <mysql-container-id> mysql -p todos 连接到 MySQL 查看数据

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todos              |
+--------------------+
5 rows in set (0.00 sec)

mysql> 
mysql> use todos;
Database changed
mysql> 
mysql> select * from todo_items;
+--------------------------------------+------+-----------+
| id                                   | name | completed |
+--------------------------------------+------+-----------+
| 7d57e3e3-c01e-43e1-b34a-28efa4022e0d | 111  |         0 |
| bc071de0-77d5-486f-8fb6-c9b9172ded6a | 222  |         1 |
| 29037f15-20ed-4120-8f59-bbe260d57c0e | 333  |         0 |
+--------------------------------------+------+-----------+
3 rows in set (0.00 sec)

使用 Docker Compose

Docker Compose 是一个旨在帮助定义和共享多容器应用程序的工具。使用Compose,使用Compose,我们可以创建一个YAML文件来定义服务,并使用一个命令将所有服务启动或关闭。

使用Compose的一个重要优势是,您可以在一个文件中定义应用程序堆栈,将其保留在项目存储库的根目录下(现在已进行版本控制),并轻松地让他人贡献到您的项目中。其他人只需要克隆您的存储库并启动Compose应用程序即可。实际上,在GitHub / GitLab上可能会看到现在有很多项目都在使用这种方法。

安装 Docker Compose

常用命令

Docker 官网文档 命令

systemctl start docker
systemctl stop docker
systemctl restart docker

docker search nginx # 检索 Nginx
docker pull nginx # 下载最新标签的 Nginx
docker images # 列出本地镜像
docker run -d --name nginx -p 80:80 nginx # 以后台模式运行 Nginx 镜像, 指定名称为 nginx, 指定端口印射 物理端口:容器端口=81:80, 容器内 nginx 默认运行在 80 端口, 指定通过物理机 81 端口访问容器的 80 端口
docker ps # 列出运行容器
docker ps -a # 列出全部容器
docker exec -it 容器id/name /bin/bash # 进入运行中的容器, -it:交互方式进入容器; 容器id只需要前几位能和其他容器区分开即可, 其他地方同样适用
exit # 退出容器
docker stop 容器id/name # 停止容器
docker rm 容器id # 删除容器
docker rm -f nginx # 删除镜像

docker commit -a mrathena -m test-commit nginx mrathena/nginx:20230616 # 将当前的容器(name:nginx)做成镜像, REPOSITORY:mrathena/nginx, TAG:20230616

帮助命令

docker version # 版本信息
docker info # 系统信息, 包括镜像和容器的数量等
docker 命令 --help

镜像命令

docker images

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

[root@mrathena yum.repos.d]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   5 months ago   13.3kB

# REPOSITORY: 镜像的仓库源
# TAG:        镜像的标签(版本)
# IMAGE ID:   镜像的id
# CREATED:    镜像的创建时间
# SIZE:       镜像的大小

# 可选项
-a, --all 		# 列出所有镜像
-q, --quiet		# 只显示镜像id

docker search

docker search [OPTIONS] TERM

[root@mrathena yum.repos.d]# docker search mysql
NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                            MySQL is a widely used, open-source relation…   12216     [OK]       
mariadb                          MariaDB Server is a high performing open sou…   4689      [OK]       
mysql/mysql-server               Optimized MySQL Server Docker images. Create…   907                  [OK]
percona                          Percona Server is a fork of the MySQL relati…   570       [OK]       
phpmyadmin                       phpMyAdmin - A web interface for MySQL and M…   465       [OK]       
mysql/mysql-cluster              Experimental MySQL Cluster Docker images. Cr…   93                   
centos/mysql-57-centos7          MySQL 5.7 SQL database server                   92                   
bitnami/mysql                    Bitnami MySQL Docker Image                      64                   [OK]
circleci/mysql                   MySQL is a widely used, open-source relation…   25                   
ubuntu/mysql                     MySQL open source fast, stable, multi-thread…   24                   
mysql/mysql-router               MySQL Router provides transparent routing be…   23                   
arey/mysql-client                Run a MySQL client from a docker container      20                   [OK]
google/mysql                     MySQL server for Google Compute Engine          19                   [OK]
mysqlboy/docker-mydumper         docker-mydumper containerizes MySQL logical …   3                    
mysqlboy/mydumper                mydumper for mysql logcial backups              3                    
bitnami/mysqld-exporter                                                          2                    
ibmcom/mysql-s390x               Docker image for mysql-s390x                    1                    
mysqlboy/percona-server          Percona-Server a MySQL Fork with enhancement…   1                    [OK]
mirantis/mysql                                                                   0                    
mysqlboy/elasticsearch                                                           0                    
mysqleatmydata/mysql-eatmydata                                                   0                    
mysql/mysql-operator             MySQL Operator for Kubernetes                   0                    
mysql/ndb-operator               MySQL NDB Operator for Kubernetes               0                    
cimg/mysql                                                                       0                    
ibmcom/tidb-ppc64le              TiDB is a distributed NewSQL database compat…   0 

[root@mrathena yum.repos.d]# docker search mysql --filter=STARS=9999
NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql     MySQL is a widely used, open-source relation…   12216     [OK]  

docker pull

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

[root@mrathena yum.repos.d]# docker pull mysql
Using default tag: latest # 不写TAG默认就是 latest 最新的
latest: Pulling from library/mysql
72a69066d2fe: Pull complete # 分层下载, docker image 核心, 联合文件系统
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
688ba7d5c01a: Pull complete 
00e060b6d11d: Pull complete 
1c04857f594f: Pull complete 
4d7cfa90e6ea: Pull complete 
e0431212d27d: Pull complete 
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址

[root@mrathena yum.repos.d]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Already exists # 可以直接利用已经存在的部分文件
93619dbc5b36: Already exists 
99da31dd6142: Already exists 
626033c43d70: Already exists 
37d5d7efb64e: Already exists 
ac563158d721: Already exists 
d2ba16033dad: Already exists 
0ceb82207cd7: Pull complete 
37f2405cae96: Pull complete 
e2482e017e53: Pull complete 
70deed891d42: Pull complete 
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi

docker rmi [OPTIONS] IMAGE [IMAGE…]

# 删除指定容器
docker rmi -f 容器id
# 删除多个容器
docker rmi -f 容器id 容器id 容器id
# 删除全部容器, 参数替换, 拿 $() 执行结果作为参数来删除
docker rmi -f $(docker images -aq)

容器命令

有镜像才可以创建容器, 下载一个linux镜像来学习测试

docker pull centos

docker run 创建容器

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

# 参数说明
--name="name" 			# 容器名字 用来区分容器
-d						# 后台方式运行
-it						# 使用交互方式运行, 方便我们进入容器查看内容
-p						# 指定容器端口, -p:80:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口 (最常用)
	-p 容器端口
	容器端口
-P						# 随机端口

# 测试, 启动并进入容器, 主机名发生变化
[root@mrathena yum.repos.d]# docker run -it centos /bin/bash
[root@434d27e6adde /]# 

# 查看容器内容
[root@434d27e6adde /]# ls  
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 退出
exit 			# 停止容器并退出
Ctrl + P + Q 	# 不停止容器推出

docker ps 列出容器

docker ps [OPTIONS]

[root@mrathena yum.repos.d]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

[root@mrathena yum.repos.d]# docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED             STATUS                            PORTS     NAMES
434d27e6adde   centos        "/bin/bash"   3 minutes ago       Exited (127) About a minute ago             intelligent_cohen
2966bf3f4cbd   hello-world   "/hello"      About an hour ago   Exited (0) About an hour ago                determined_blackwell

# 参数说明
		# 列出当前正在运行的容器
-a		# 列出当前正在运行的容器 + 历史运行的容器
-n=?	# 列出最近创建的几个容器
-q		# 只显示容器的编号

docker rm 删除容器

docker rm 容器id					# 删除指定容器, 不能删除正在运行的容器, 强制删除 rm -rf
docker rm -f $(docker ps -aq)
docker ps -a -q | xargs docker rm

启动和停止容器

docker start 容器id
docker restart 容器id
docker stop 容器id		# 停止运行的容器
docker kill 容器id		# 强制停止运行的容器

其他常用命令

后台启动
# 后台启动
docker run -d centos
# 通过 docker ps 发现 centos 停止了, 常见的坑, docker 容器使用后台运行时要求必须有一个前台进程, 如果docker发现容器中没有应用在运行就会自动停止
docker logs 查看日志
docker logs --help
docker logs -ft --tail 10 afd77ec4f3a8
# 自己写个shell脚本
"while true; do echo hello; sleep 1; done"

[root@mrathena yum.repos.d]# docker run -d centos /bin/sh -c "while true; do echo hello; sleep 1; done"
a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818

[root@mrathena yum.repos.d]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
a0dc75d7d93a   centos    "/bin/sh -c 'while t…"   3 seconds ago   Up 3 seconds             serene_cannon
[root@mrathena yum.repos.d]# docker logs -ft --tail 10 a0dc75d7d93a
2022-03-06T17:36:55.221020791Z hello
2022-03-06T17:36:56.222716774Z hello
2022-03-06T17:36:57.226031883Z hello
docker top 查看容器中的进程信息
[root@mrathena yum.repos.d]# docker top a0dc75d7d93a
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4705                4686                0                   01:36               ?                   00:00:00            /bin/sh -c while true; do echo hello; sleep 1; done
root                4958                4705                0                   01:40               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
docker inspect 查看容器的元数据
[root@mrathena yum.repos.d]# docker inspect a0dc75d7d93a
[
    {
        "Id": "a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818",
        "Created": "2022-03-06T17:36:47.00014358Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true; do echo hello; sleep 1; done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 4705,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-03-06T17:36:47.202311706Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818/hostname",
        "HostsPath": "/var/lib/docker/containers/a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818/hosts",
        "LogPath": "/var/lib/docker/containers/a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818/a0dc75d7d93a5269604695f20655057e387412ab663722bd3486d5802ec7b818-json.log",
        "Name": "/serene_cannon",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/4a44aee72d0f2c025fdbebf35b47c87a31f48ecc342db821d20642320772e783-init/diff:/var/lib/docker/overlay2/f06b910a8a08366072e81f2eadf81bb94b9500bfd791b204dbfe80ce01ebd210/diff",
                "MergedDir": "/var/lib/docker/overlay2/4a44aee72d0f2c025fdbebf35b47c87a31f48ecc342db821d20642320772e783/merged",
                "UpperDir": "/var/lib/docker/overlay2/4a44aee72d0f2c025fdbebf35b47c87a31f48ecc342db821d20642320772e783/diff",
                "WorkDir": "/var/lib/docker/overlay2/4a44aee72d0f2c025fdbebf35b47c87a31f48ecc342db821d20642320772e783/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "a0dc75d7d93a",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true; do echo hello; sleep 1; done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "9aa9a53c095fc39d31cd7f2974bf08ff3b3546e2cde7603209d21107467def99",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/9aa9a53c095f",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "416ebf084c86aea3e061976abce95dfdc09cda0e9622dcc08c721bd6dbe10306",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "947ffb23cceba0e0444083b9a63d40159a5ed24d06e88ce71ca9a014847a93eb",
                    "EndpointID": "416ebf084c86aea3e061976abce95dfdc09cda0e9622dcc08c721bd6dbe10306",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
进入当前运行的容器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值