Docker chapter 4 Network

Remember that containers, by default, run in isolation and don't know anything about other processes or containers on the same machine. So, how do you allow one container to talk to another? The answer is networking. If you place the two containers on the same network, they can talk to each other.

There are two ways to put a container on a network:

  • Assign the network when starting the container.
  • Connect an already running container to a network.

在 Docker 中,网络是容器之间通信的方式。每个 Docker 容器都会连接到一个或多个网络,这些网络可以是 Docker 默认创建的,也可以是用户自定义的。

  1. 在启动容器时指定网络:当你使用 docker run 命令启动一个容器时,你可以使用 --network 选项来指定容器应该连接到哪个网络。例如,docker run --network my_network my_image 会启动一个新的容器,这个容器连接到 my_network 网络,并运行 my_image 镜像。

  2. 将已经运行的容器连接到网络:如果一个容器已经在运行,你可以使用 docker network connect 命令来将它连接到一个网络。例如,docker network connect my_network my_container 会将 my_container 容器连接到 my_network 网络。

在 Docker 中,网络可以用于实现容器之间的通信,例如,一个 Web 服务器容器可以通过网络与一个数据库容器通信。此外,网络还可以用于控制容器的网络访问,例如,你可以创建一个网络,只有连接到这个网络的容器才能访问互联网

Docker 网络主要用于控制和管理容器之间以及容器与宿主机之间的通信。以下是 Docker 网络的一些常见应用场景:

  1. 容器之间的通信:Docker 网络可以使同一网络中的容器之间进行通信。例如,你可能有一个 Web 服务器容器和一个数据库容器,你可以将它们都连接到同一个网络,这样 Web 服务器就可以访问数据库了。

  2. 服务发现:在同一 Docker 网络中,容器可以通过容器名来相互访问,这就是 Docker 的服务发现特性。例如,如果你有两个在同一网络中的容器,名为 web 和 db,那么 web 容器可以通过主机名 db 来访问 db 容器。

  3. 网络隔离:你可以创建多个 Docker 网络来实现网络隔离,即只有在同一网络中的容器才能相互通信。这可以提高应用的安全性,因为它可以防止未授权的容器访问你的应用。

  4. 连接到外部网络:Docker 容器可以连接到宿主机的网络,这使得容器可以访问宿主机的网络资源,也可以被宿主机的网络访问。

  5. 限制网络访问:你可以通过 Docker 网络来限制容器的网络访问。例如,你可以创建一个没有外部网络访问权限的 Docker 网络,然后将你的容器连接到这个网络,这样这个容器就不能访问互联网了。

note1: 

create a network

docker network create mynetwork

note 2 :

run a mysql container and mount it to a network

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

docker run 命令,用于启动一个新的 Docker 容器。下面是这个命令的各个参数的含义:

  • -d:这个参数表示以“分离”模式运行容器,即在后台运行容器并打印容器 ID。

  • --network todo-app:这个参数将容器连接到 todo-app 网络。如果 todo-app 网络不存在,你需要先创建它。

  • --network-alias mysql:这个参数为容器在网络中的别名设置为 mysql。在同一网络中的其他容器可以使用这个别名来访问这个容器。

  • -v todo-mysql-data:/var/lib/mysql:这个参数创建一个名为 todo-mysql-data 的卷,并将它挂载到容器的 /var/lib/mysql 目录。卷是 Docker 的一种数据存储机制,它可以将数据持久化并在容器之间共享。

  • -e MYSQL_ROOT_PASSWORD=secret 和 -e MYSQL_DATABASE=todos:这两个参数设置了环境变量。MYSQL_ROOT_PASSWORD 设置了 MySQL 的 root 用户的密码,MYSQL_DATABASE 设置了要创建的数据库的名称。

  • mysql:8.0:这是要运行的 Docker 镜像的名称和标签。这里,镜像的名称是 mysql,标签是 8.0,所以这个命令会运行 MySQL 8.0。

所以,这个命令会在后台启动一个新的 MySQL 8.0 容器,这个容器连接到 todo-app 网络,并使用别名 mysql。这个容器使用 todo-mysql-data 卷来存储数据,root 用户的密码设置为 secret,并创建一个名为 todos 的数据库。

-e 是 --env 的缩写,它们都是 docker run 命令的参数,用于设置环境变量。你可以使用 -e 或 --env 来传递环境变量给 Docker 容器,这些环境变量可以在容器内的应用程序中使用。例如,-e MYSQL_ROOT_PASSWORD=secret 就是设置了一个名为 MYSQL_ROOT_PASSWORD 的环境变量,其值为 secret 

在这个 docker run 命令中,mysql:8.0 就是 Docker 镜像的名称。这个命令会启动一个新的 Docker 容器,并运行 mysql:8.0 镜像。

mysql:8.0 是 Docker 镜像的名称和标签。mysql 是镜像的名称,8.0 是镜像的标签。标签通常用于标识镜像的版本。在这个例子中,8.0 表示这个镜像是 MySQL 8.0 的版本。

当你运行 docker run 命令时,Docker 会首先检查本地是否有 mysql:8.0 镜像。如果没有,Docker 会从 Docker Hub(默认的 Docker 镜像仓库)下载这个镜像。然后,Docker 会使用这个镜像来启动一个新的容器。

note 2.5 :

explain the param --network-alias 

在 Docker 中,--network-alias 参数用于为容器在特定网络中设置别名。这个别名可以被同一网络中的其他容器用来访问这个容器。

当你在 Docker 网络中运行一个容器,并为其设置了网络别名时,Docker 的内部 DNS 服务器会将这个别名解析为该容器的 IP 地址。这意味着,同一网络中的其他容器可以通过这个别名来访问这个容器,而不需要知道它的 IP 地址。

例如,如果你运行一个 MySQL 容器,并为其在 my-network 网络中设置了 mysql 作为网络别名,那么在 my-network 网络中的其他容器就可以通过 mysql 这个名字来访问这个 MySQL 容器。

这种方式可以简化容器之间的通信,因为你不需要记住或管理容器的 IP 地址,只需要知道容器的网络别名就可以了

note 3 :

login  the   running    mysql  container   where network is ( --network todo-app --network-alias mysql ) 

docker exec -it  mysql -u root -p

 Docker chapter 4 Network_第1张图片

note4 :

HOW CONNECT THE MYSQL CONTAINER ?   answer is :  IP !

Now that you know MySQL is up and running, you can use it. But, how do you use it? If you run another container on the same network, how do you find the container? Remember that each container has its own IP address.

note 5:

about :nicolaka/netshoot 

nicolaka/netshoot 是一个 Docker 镜像,它包含了大量的网络诊断工具,可以用于调试和诊断 Docker 容器的网络问题。

这个镜像包含了如 netstatcurlipnmapdig 等常用的网络工具,你可以使用 docker run 命令来启动一个 nicolaka/netshoot 容器,并在这个容器中运行这些工具来诊断网络问题。

例如,你可以使用 nicolaka/netshoot 来查看容器的网络接口,检查网络连接,测试网络延迟,查看 DNS 解析结果等。这对于理解和解决 Docker 容器的网络问题非常有帮助。

需要注意的是,nicolaka/netshoot 是一个诊断工具,它并不应该在生产环境中使用。在完成诊断后,你应该停止并删除 nicolaka/netshoot 容器,以避免占用系统资源。

note 6:

run  nicolaka/netshoot  with previous network 

docker run -it --network todo-app nicolaka/netshoot

 Now、the mysql container and nicolaka/netshoot container running  at the same network!

note 7:

inquier  mysql-container's   ip address

dig mysql 

dig 是一个 DNS 查询工具,用于查询 DNS 名称服务器并调试 DNS 问题。dig 命令的一般格式是 dig @server name type,其中 @server 是你要查询的 DNS 服务器,name 是你要查询的域名,type 是你要查询的记录类型。

例如,dig mysql 命令会查询 mysql 域名的 A 记录(即 IP 地址)。如果你没有指定 DNS 服务器,dig 命令会使用你的系统默认的 DNS 服务器。

 Docker chapter 4 Network_第2张图片

In the "ANSWER SECTION", you will see an A record for mysql that resolves to 172.23.0.2 (your IP address will most likely have a different value). While mysql isn't normally a valid hostname, Docker was able to resolve it to the IP address of the container that had that network alias. Remember, you used the --network-alias earlier.

What this means is that your app only simply needs to connect to a host named mysql and it'll talk to the database

about  --network-alias's detail please go back top introduction

note 8:

connect the mysql container (and set env variables)

The todo app supports the setting of a few environment variables to specify MySQL connection settings. They are:

MYSQL_HOST - the hostname for the running MySQL server
MYSQL_USER - the username to use for the connection
MYSQL_PASSWORD - the password to use for the connection
MYSQL_DB - the database to use once connected

 you can setting of a few environment variables to specify MySQL connection settings

docker run -d \
  -e MYSQL_HOST=my-mysql-host \
  -e MYSQL_USER=my-user \
  -e MYSQL_PASSWORD=my-password \
  -e MYSQL_DB=my-database \
  my-app-image

 WARNING :

  • hardcoded-credentials Embedding credentials in source code risks unauthorized access

While using env vars to set connection settings is generally accepted for development, it's highly discouraged when running applications in production. Diogo Monica, a former lead of security at Docker, wrote a fantastic blog post explaining why.

A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases, these secrets are mounted as files in the running container. You'll see many apps (including the MySQL image and the todo app) also support env vars with a _FILE suffix to point to a file containing the variable.

As an example, setting the MYSQL_PASSWORD_FILE var will cause the app to use the contents of the referenced file as the connection password. Docker doesn't do anything to support these env vars. Your app will need to know to look for the variable and get the file contents.

在开发环境中,通常可以使用环境变量(env vars)来设置这些信息。然而,Diogo Monica(Docker 的前安全主管)在他的博客文章中解释了为什么在生产环境中这样做是不被推荐的。主要原因是环境变量可能会被其他进程或日志记录等方式泄露。

一个更安全的方法是使用你的容器编排框架提供的秘密(secret)支持。在大多数情况下,这些秘密会被挂载为运行容器中的文件。你会看到许多应用(包括 MySQL 镜像和 todo 应用)也支持带有 _FILE 后缀的环境变量,用来指向包含变量的文件。

例如,设置 MYSQL_PASSWORD_FILE 变量会使应用使用引用的文件的内容作为连接密码。Docker 不会做任何事情来支持这些环境变量。你的应用需要知道去查找这个变量并获取文件内容。

这种方法可以更安全地处理敏感信息,因为即使环境变量被泄露,攻击者也无法直接获取到敏感信息,他们还需要获取到存储这些信息的文件。

note 9 : 

Now execute    getting-started-app  container  connect to the   mysql container 

docker run -dp 127.0.0.1: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"
  • -dp 127.0.0.1:3000:3000:这个参数用于将容器的 3000 端口映射到宿主机的 3000 端口。d 表示以后台模式运行容器,p 表示端口映射。
  • -w /app:设置容器的工作目录为 /app
  • -v "$(pwd):/app":将当前目录($(pwd))挂载到容器的 /app 目录。这样,你在宿主机上对当前目录的修改会同步到容器中。
  • --network todo-app:将容器连接到 todo-app 网络。
  • -e MYSQL_HOST=mysql:设置环境变量 MYSQL_HOST 的值为 mysql
  • -e MYSQL_USER=root:设置环境变量 MYSQL_USER 的值为 root
  • -e MYSQL_PASSWORD=secret:设置环境变量 MYSQL_PASSWORD 的值为 secret
  • -e MYSQL_DB=todos:设置环境变量 MYSQL_DB 的值为 todos
  • node:18-alpine:使用的 Docker 镜像是 node:18-alpine
  • sh -c "yarn install && yarn run dev":在容器中运行的命令。这个命令会先安装依赖,然后运行开发服务器。

这个命令会启动一个 Node.js 应用,该应用连接到 todo-app 网络中的 MySQL 服务器,并监听 3000 端口。

-w /app 是 Docker 命令的一个参数,-w 是 --workdir 的缩写。这个参数用于设置 Docker 容器的工作目录。

在你的例子中,-w /app 设置了容器的工作目录为 /app。这意味着当你在容器内运行命令时,这些命令会在 /app 目录下执行。

例如,如果你在容器内运行 ls 命令,它会列出 /app 目录下的文件,而不是容器的根目录下的文件。同样,如果你在容器内运行 npm install 命令,它会在 /app 目录下安装依赖。

设置工作目录可以使得在容器内运行命令更加方便,因为你不需要每次都指定命令的完整路径

sh 是一个 Unix shell,也就是命令行解释器。它是 Bourne shell(由 Stephen Bourne 在 Bell Labs 开发)的直接后代,因此也被称为 Bourne shell。在许多 Unix 和 Linux 系统中,sh 通常是指向 Bourne shell 或其兼容版本(如 Bash、Dash)的符号链接。

sh -c "yarn install && yarn run dev" 这个命令的含义是:使用 sh shell 来执行 -c 参数后面的命令字符串。这个字符串中包含了两个命令:yarn install 和 yarn run dev,它们由 && 连接。&& 是一个逻辑运算符,表示只有当前面的命令(yarn install)成功执行后,才会执行后面的命令(yarn run dev)。

所以,这个命令的整体含义是:首先使用 Yarn 安装依赖,如果安装成功,然后使用 Yarn 运行 dev 脚本。

docker run -dp 127.0.0.1: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" 

中的 /app是 目录是自动创建的吗,加入当前路径是 /Users/guoyongkun/Desktop/docker/getting-started-app 。用一个demo表示运行起来后的文件夹路径

在 Docker 中,当你设置工作目录(使用 -w 或 --workdir 参数)或挂载卷(使用 -v 或 --volume 参数)时,如果指定的目录在容器中不存在,Docker 会自动创建它。

在你的命令中,-w /app 设置了容器的工作目录为 /app-v "$(pwd):/app" 将宿主机的当前目录(/Users/guoyongkun/Desktop/docker/getting-started-app)挂载到容器的 /app 目录。所以,如果 /app 目录在容器中不存在,Docker 会自动创建它。

运行命令后,容器的文件系统会有如下的结构:

/
└── app
    ├── file1
    ├── file2
    ├── ...
    └── fileN

这里,file1file2 等文件是从宿主机的 /Users/guoyongkun/Desktop/docker/getting-started-app 目录复制过来的。因为你使用了卷挂载,所以这些文件在容器中的修改会同步到宿主机,反之亦然。

note 10 :

 print container logs 

docker exec -it  mysql -p todos

docker logs 命令用于获取和查看 Docker 容器的日志。在这个命令中, 需要替换为你想要查看日志的容器的 ID。

-f 参数是 --follow 的缩写,用于实时跟踪和显示容器的日志输出。当你使用 -f 参数运行 docker logs 命令时,命令行界面会持续显示新的日志条目,直到你停止命令的执行。

所以,docker logs -f  命令的含义是:实时跟踪和显示指定容器的日志输出。

note 11 :

 open local 3000 port and add some items;

execute query the mysql table (todo_items)

Docker chapter 4 Network_第3张图片

Docker chapter 4 Network_第4张图片

note 12:

inpsect a network and get  all of container that connect it 

docker network  inspect  networID/name

Docker chapter 4 Network_第5张图片

and more commands

Docker chapter 4 Network_第6张图片

你可能感兴趣的:(docker,docker,容器,运维)