Docker和Docker Compose的基础知识

我希望能写一篇能够理解Docker和Docker Compose基础知识的文章。

我将技术类文章的发布位置迁移到了自己的博客上。我在面向初学者的AWS和其他广泛的技术领域上努力发布文章,如果方便的话,请也参考一下这里!

准备好了

undefined
    docker
$ docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:13:02 2018
 OS/Arch:      darwin/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: true
    docker-compose
$ docker-compose version
docker-compose version 1.21.1, build 5a3f1a3
docker-py version: 3.3.0
CPython version: 3.6.4
OpenSSL version: OpenSSL 1.0.2o  27 Mar 2018

容器技术

Docker Hub中存储了各种可用于Docker的服务器镜像。
主要用途为

    • 利用したいものをそのまま利用する (Databaseやkvsなどすでにアプリケーションが機能として盛り込まれたイメージもたくさんある)

 

    利用したい環境の土台となるイメージを利用し、それをカスタマイズして自分用に追加で機能が盛り込まれたイメージ作成し利用する

试运行(容器的开启和关闭)

首先我想要掌握 Docker 的基础知识,所以我将尝试使用一个安装有 CentOS 操作系统的简单镜像。

$ docker run centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
469cfcc7a4b3: Pull complete
Digest: sha256:989b936d56b1ace20ddf855a301741e52abca38286382cba7f44443210e96d16
Status: Downloaded newer image for centos:latest

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
9a9ebeb47eb4        centos              "/bin/bash"         7 seconds ago       Exited (0) 10 seconds ago                       boring_hamilton

我执行了三个命令。
首先执行命令 “docker run centos” 来启动名为 centos 的镜像。
如果本地存在指定的镜像,则从那里启动;如果不存在,则从前面提到的Docker Hub下载并启动。

下面是您要求的中文翻译:
接下来是 docker ps。该命令用于显示正在运行的 Docker(容器)列表。然而,理应没有任何内容显示出来。

最后执行 docker ps -a 命令。通过添加 -a 选项,将会列出所有已停止的容器。在这里,首次启动的容器应该会列为已停止的。已停止的容器可以再次恢复,因此会保留为停止状态的容器。但它会占用机器的资源(硬盘),如果不打算重新启动,可以使用以下命令进行删除。

$ docker rm 9a9ebeb47eb4
9a9ebeb47eb4

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

在中国,这个值被称为容器ID(9a9ebeb47eb4),它是指示特定容器的ID。因此,在每个环境中,这个值应该是不同的,可以使用docker ps (-a) 命令来获取显示的ID。(还可以通过指定名称来使用更明确的标签来确定容器)

提示:给容器ID贴上标签

# name をコンテナに付与して操作する例

$ docker run --name mycentos centos
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
4f2b3e7b91b5        centos              "/bin/bash"         3 seconds ago       Exited (0) 7 seconds ago                       mycentos
$ docker rm mycentos
mycentos

在容器内的操作

虽然应该是使用CentOS镜像启动,但却立即关闭,这样没有意义。当通过ps命令查看时,可以确认COMMAND=”/bin/bash”,说明启动了CentOS并执行了/bin/bash(这是镜像中预先配置的初始启动命令),但由于没有TTY,因此被立即退出(exit(0)),导致容器也处于已关闭状态。

只需在运行`docker run`时加入`-it`选项即可启动并使容器可操作。

$ docker run -it centos

[root@c7827f28ee8d /]#
[root@c7827f28ee8d /]# ls  /
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@c7827f28ee8d /]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@c7827f28ee8d /]# exit
exit

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
c7827f28ee8d        centos              "/bin/bash"         5 minutes ago       Exited (0) 15 seconds ago                       suspicious_liskov

使用`-it`选项启动后,提示符会发生变化。控制台变为操作容器内部的状态。与登录并在CentOS环境中进行操作相同的操作变得可行。当通过`exit`完成工作并退出时,控制权将返回到Mac端,容器也将停止运行。

提示:Docker镜像的选择方法和镜像管理

要确认使用的镜像是在 CentOS 系统上首次使用时从 Docker Hub 下载的,可以使用 docker images 命令进行检查。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              e934aafc2206        7 weeks ago         199MB

镜像通过 REPOSITORY:TAG 进行唯一标识。在这个例子中,仅指定了 centos,这意味着使用最新版的 centos,即 centos:latest,如Docker Hub所述的 centos7。如果想使用 centos6,则可以通过以下方式通过 TAG 指定。以下是选择 centos6 时的操作步骤。

$ docker run -it centos:6
Unable to find image 'centos:6' locally
6: Pulling from library/centos
987d765a926d: Pull complete
Digest: sha256:67b491e26d566ee9c55578bfd6115554a6e1b805a49502ead32cb1a324466f2c
Status: Downloaded newer image for centos:6

[root@01a74d994685 /]# cat /etc/redhat-release
CentOS release 6.9 (Final)
[root@01a74d994685 /]# exit
exit

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              6                   70b5d81549ec        7 weeks ago         195MB
centos              latest              e934aafc2206        7 weeks ago         199MB

可以删除不需要的图像资源,因为这样会浪费资源。在这种情况下,可以使用docker rmi命令。

$ docker rmi 70b5d81549ec
Error response from daemon: conflict: unable to delete 70b5d81549ec (must be forced) - image is being used by stopped container 01a74d994685
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
01a74d994685        centos:6            "/bin/bash"         2 minutes ago       Exited (0) 2 minutes ago                        nifty_swanson
c7827f28ee8d        centos              "/bin/bash"         20 minutes ago      Exited (0) 14 minutes ago                       suspicious_liskov
$ docker rm 01a74d994685
01a74d994685
$ docker rmi 70b5d81549ec
Untagged: centos:6
Untagged: centos@sha256:67b491e26d566ee9c55578bfd6115554a6e1b805a49502ead32cb1a324466f2c
Deleted: sha256:70b5d81549ec19aa0a10f8660ba5e1ab9966008dbb1b6c5af3d0ecc8cff88eef
Deleted: sha256:e0dec291ae94d0f486c2a6a98732bac23e45b0914f8f9e67c57c5e6a2cd7fed7
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              e934aafc2206        7 weeks ago         199MB

通过运行docker images命令,可以查看到所需删除的镜像ID。在上述示例中,尝试使用docker rmi命令删除centos6镜像,但出现了错误,删除操作失败。这是因为有一个正在停止中的容器正在使用该镜像。在删除容器后再次执行镜像删除操作,可以确认删除成功。

容器的附加和分离

嗯,按照步驟進行,我認為目前容器的狀態是centos7容器停止中。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
c7827f28ee8d        centos              "/bin/bash"         25 minutes ago      Exited (0) 20 minutes ago                       suspicious_liskov

要重新启动这个,执行`docker restart`

$ docker restart c7827f28ee8d
c7827f28ee8d
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c7827f28ee8d        centos              "/bin/bash"         27 minutes ago      Up 21 seconds                           suspicious_liskov
$

从“状态显示为”Up”,可以看出它再次启动了。然而,控制台是在Mac中,而不是在已启动的容器内。要再次进入容器,只需执行docker attach命令即可。

$ docker attach c7827f28ee8d
[root@c7827f28ee8d /]# ls

如果在工作过程中想要将控制权还给Mac一次,那么只需要使用”exit”命令,就像之前所说,容器将变为停止状态,如果想要重新使用,就必须使用”docker restart”重新开始,这样效率低下。如果希望在容器继续运行的情况下将控制权还给Mac,只需在容器内按下Ctrl + p q(按住Ctrl键然后依次按下p和q键即可)。这样能够让控制权回到Mac而容器仍然保持运行。将控制权从容器返回Mac的这种操作称为分离(Detach),与附加(Attach)操作相反。

容器(镜像)的个性化定制

我要尝试自定义容器。在正在运行的CentOS中安装httpd并将其转化为Web服务器。(在DockerHub上,有httpd的镜像可用,因此可以轻松地使用Web服务器。但由于这次是为了学习,所以将从原始的CentOS自行构建)。

$ docker attach c7827f28ee8d
[root@c7827f28ee8d /]# yum update -y
[root@c7827f28ee8d /]# yum install httpd -y

httpd が起動しますが、コンテナ内での操作になります。

# systemctl
Failed to get D-Bus connection: Operation not permitted

当启动容器时,会显示一个不能授权的消息。如果启动容器,通常情况下我们可以控制该启动进程(在此情况下为/bin/bash及其子进程),但不允许控制更高级的进程。虽然有一种避免这种情况的启动方法,但一般情况下很少使用。

那么,如何启动httpd呢?请按以下方式启动。

# /usr/sbin/httpd -DFOREGROUND

由于在前台启动,控制台无法控制httpd循环,因此无法进行操作。首先,我们将确认启动已经完成,然后再解释如何处理。在mac上打开另一个控制台,然后在该控制台内执行容器中的命令。

$ docker exec c7827f28ee8d ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  11828  2908 pts/0    Ss   04:01   0:00 /bin/bash
root        15  0.0  0.3 224028  7612 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
apache      16  0.0  0.2 224028  6052 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
apache      17  0.0  0.2 224028  6052 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
apache      18  0.0  0.2 224028  6052 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
apache      19  0.0  0.2 224028  6052 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
apache      20  0.0  0.2 224028  6052 pts/0    S+   04:01   0:00 /usr/sbin/httpd -DFOREGROUND
root        33  0.0  0.1  51716  3508 ?        Rs   04:02   0:00 ps -aux

$ docker exec c7827f28ee8d curl localhost
...
$ docker exec -it 00320d5b01de /bin/bash
↑ exec を -it 付きで /bin/bash 起動するとコンテナの中に入れる

确实可以确定httpd已经启动了。 (※ 使用了docker exec命令,这个命令用于在指定容器内执行参数命令。如果在另一台Mac上使用docker attach,则无法达到目的,这种情况下应该使用exec。可以尝试attach后的效果也是可以的)

现在,虽然启动了,但我觉得这样还不够实用,所以继续推进。

创建图像

创建一个自定义的容器并在CentOS映像上安装了httpd。将其保存为映像。首先停止正在运行的httpd(按Ctrl+c),然后使用exit命令退出容器并将其置于停止状态。

[root@c7827f28ee8d /]# exit
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
c7827f28ee8d        centos              "/bin/bash"         About an hour ago   Exited (0) 7 seconds ago                       suspicious_liskov

使用docker commit命令将已停止的容器(c7827f28ee8d)转换为镜像。

$ docker commit c7827f28ee8d mycentos_with_httpd
sha256:d1b7ab953d99d9675e2b8ef7b02bbed765845474c6fe1d7195e66f3640f7f3d2
$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED                  SIZE
mycentos_with_httpd   latest              d1b7ab953d99        Less than a second ago   453MB
centos                latest              e934aafc2206        7 weeks ago              199MB

通过以上操作,在本地创建了一个名为mycentos_with_httpd的CentOS镜像,并且该镜像中已经安装了httpd。通过尝试使用这个镜像启动容器,我们可以确认httpd已经预装好了。

$ docker run -it mycentos_with_httpd
[root@2184a0e23ad1 /]# ls -l /usr/sbin/httpd
-rwxr-xr-x 1 root root 523688 Apr 20 18:11 /usr/sbin/httpd
[root@2184a0e23ad1 /]# exit
exit

启动容器守护程序

让我们启动一个包含httpd的容器,并在其中启动httpd。之前我们登录后使用命令 /usr/sbin/httpd -DFOREGROUND 手动启动了httpd,但是现在我们可以通过将此命令作为docker run的参数来实现同样的效果。另外,如果我们添加 -d 选项,可以将容器的启动变为守护进程。现在真正去尝试一下。

$ docker run -d mycentos_with_httpd /usr/sbin/httpd -DFOREGROUND
9dee4a08b3e674031c142ffaafacf616743e57648b80af4276cf9eb19b10cfda
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS               NAMES
9dee4a08b3e6        mycentos_with_httpd   "/usr/sbin/httpd -DF…"   3 seconds ago       Up 11 seconds                           practical_goldstine

在执行docker run命令后,可以继续在Mac的控制下运行。但是当查看docker ps时,可以看到容器正在运行。尝试在前一个实验中尝试在另一个控制台中进行确认,结果应该是相同的,应该可以确认在容器内正在运行httpd。

如果要停止在这个状态下启动的容器,只需执行命令 docker stop。

$ docker stop 9dee4a08b3e6
9dee4a08b3e6

提示:使用 rm 命令在容器启动时轻松清理一下。

当尝试不断操作时,可能会产生大量停止的容器,可以通过使用”docker ps -a”命令来确认这些容器。然而,逐一使用”docker rm”命令来删除这些容器会很麻烦。为了避免这种情况,可以在停止容器时顺便执行删除操作(当不需要再次启动时,这种方法很方便)。

$ docker run -it --rm centos
[root@fc9882d2aa18 /]# exit
exit
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
※停止中のコンテナは無い!

端口映射和卷映射

在过去的启动方式中,容器与作为主机的Mac之间没有任何关联,但是在开发过程中,需要在Mac侧与容器相关联,以便能够共享源代码文件并进行操作确认等。首先,在包含httpd的容器中启动http服务,并进行端口映射,以便从Mac侧的浏览器上确认。

$ docker run --rm -d -p 8080:80 mycentos_with_httpd /usr/sbin/httpd -DFOREGROUND

-p 8080:80 是将本地(mac)的8080端口映射到容器的80端口的指定。这样一来,在mac上打开浏览器并通过 http://localhost:8080/ 访问,就可以访问容器内的httpd了。

然后就要解释一下Volume映射。像端口一样,将Mac的文件系统映射到容器的一侧。

$ mkdir -p httpd/log
$ mkdir -p httpd/www
$ echo 'hello world' > httpd/www/index.html

$ docker run --rm -d -p 8080:80 -v `pwd`/httpd/log:/var/log/httpd -v `pwd`/httpd/www:/var/www/html mycentos_with_httpd /usr/sbin/httpd -DFOREGROUND
ef6eda9a9abdfa72ebc5bb536f0d5682138cafe6323044af90d8b619c8c96d17

当在mac上通过http://localhost:8080/访问时,将显示保存在mac上httpd/www/index.html中的“hello world”,并且httpd的访问日志将记录在mac上的httpd/log/access_log中。

$ tail -f  httpd/log/access_log
172.17.0.1 - - [26/May/2018:05:04:04 +0000] "-" 408 - "-" "-"
172.17.0.1 - - [26/May/2018:05:04:04 +0000] "-" 408 - "-" "-"
172.17.0.1 - - [26/May/2018:05:04:04 +0000] "-" 408 - "-" "-"

Dockerfile的中文简述

我创建了一个包含简化httpd的镜像,但根据基础设施即代码的思想,希望将这个过程作为代码化的步骤,并使其具有可移植性。为了实现这一点,我们使用Dockerfile进行描述。

Dockerfile是一个记录了按照规定语法创建Docker Image的文件。由于详细说明会很长,所以只介绍基本内容。基于之前创建的centos镜像并安装了httpd的图像,Dockerfile的构成如下所示。

最初写这篇文章的时候,CentOS的最新版本是7,但现在已经是8了,所以必须明确地指定FROM centos:7。(2020.9.3)

FROM centos:7

RUN yum update -y \
    && yum install httpd -y \
    && echo "hello world from dockerfile" > /var/www/html/index2.html \
    && yum clean all

ADD ./httpd/www/index.html /var/www/html/

ENTRYPOINT ["/usr/sbin/httpd", "-DFOREGROUND"]

为了减小图像的大小,进行了yum clean all操作来进行映像化。将mac上的index.html文件包含在映像中。新建了index2.html文件。还指定了要公开到外部的端口(EXPOSE),在ENTRYPOINT中可以指定默认的启动命令,以便在docker运行时使用。将这个文件保存为名为Dockerfile的文件。

(因为有关于 Dockerfile 内 EXPOSE 的说明是不必要的,所以已经将其删除。2021.8.18)

从这里开始,可以使用Docker build命令创建映像。具体来说,

$ docker build . -t mycentos_with_httpd_from_dockerfile
...
$ docker images
REPOSITORY                            TAG                 IMAGE ID            CREATED                  SIZE
mycentos_with_httpd_from_dockerfile   latest              348670313724        Less than a second ago   403MB
mycentos_with_httpd                   latest              d1b7ab953d99        About an hour ago        453MB
centos                                latest              e934aafc2206        7 weeks ago              199MB

如果这样做,将会生成图像。由于设定了ENTRYPOINT,在启动时已指定。

$ docker run -d --rm -p 8080:80 mycentos_with_httpd_from_dockerfile

可以在本地主機的8080端口上使用以下網址 http://localhost:8080/index.html 及 http://localhost:8080/index2.html 從Mac的瀏覽器上進行確認。

在Docker Hub上发布的镜像中,每个镜像都有相应的Dockerfile,可以查看它们来参考编写Dockerfile。

提示:尝试使用Docker Hub上的包含MySQL的映像

在解释docker-compose的过程中,首先需要熟悉使用DockerHub上提供的MySQL镜像。查看DockerHub上的MySQL页面后发现,latest版本是最近发布的MySQL8(截至2018/5)。但本次要使用的是MySQL5.7版本。

首先,简单地尝试运行Docker。

$ docker run mysql:5.7
Unable to find image 'mysql:5.7' locally
5.7: Pulling from library/mysql
f2aa67a397c4: Pull complete
...
Digest: sha256:f030e84582d939d313fe2ef469b5c65ffd0f7dff3b4b98e6ec9ae2dccd83dcdf
Status: Downloaded newer image for mysql:5.7
error: database is uninitialized and password option is not specified
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

图像已经被下载,但出现错误无法启动。上面写着要指定ROOT密码。所以正确答案是指定密码。

$ docker run -d --rm --env MYSQL_ROOT_PASSWORD=secret mysql:5.7
2e1ae9100124010771716cb93b2a0f843261fc3e4f28bfedee50bd7f12002b7f

这样做,MySQL容器以守护进程方式启动。使用–env参数给予环境变量来启动是一种常见的方法,记住会很有用。

实际上,尝试使用容器内的MySQL。

$ docker exec -it 2e1ae9100124 /bin/bash
root@2e1ae9100124:/#
root@2e1ae9100124:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.22 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql> show variables like 'version';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| version       | 5.7.22 |
+---------------+--------+
1 row in set (0.00 sec)

在这里使用create table创建表格,当容器被销毁并重新启动时,表格会从镜像重新启动,因此该表格不存在(如果是从停止到重新启动,文件系统将保持活动状态,因此依然存在)。

mysql> create database test;
mysql> connect test;
Connection id:    3
Current database: test
mysql> create table sample ( msg varchar(64) );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into sample values ('hello');
Query OK, 1 row affected (0.01 sec)

mysql> insert into sample values ('world');
Query OK, 1 row affected (0.01 sec)

mysql> select * from sample;
+-------+
| msg   |
+-------+
| hello |
| world |
+-------+
2 rows in set (0.00 sec)

mysql>

为了使数据库信息持久化,只需在Mac上保存数据库信息,可以使用卷映射来实现这一点。

$ mkdir -p mysql/data
$ docker run -d --rm -v `pwd`/mysql/data:/var/lib/mysql --env MYSQL_ROOT_PASSWORD=secret mysql:5.7
54cf2b615ca1e9178966ff347354f1752b968351f0ed72f73865ffc0072c170a
$ ls mysql/data/
auto.cnf        client-cert.pem     ib_logfile0     ibtmp1          private_key.pem     server-key.pem
ca-key.pem      client-key.pem      ib_logfile1     mysql           public_key.pem      sys
ca.pem          ib_buffer_pool      ibdata1         performance_schema  server-cert.pem

当启动mysql容器时,可以发现在初始化数据库时创建了初始文件,并保存在映射到mac上的卷中。在创建表并停止(丢弃)容器后,再次使用相同命令启动容器,可以确认数据被持久化保存下来。

当检查此次使用的MySQL5.7 Dockerfile时,可以看到在启动时会执行docker-entrypoint.sh脚本。

$DATADIR が存在しない場合のみMySQLの初期DBの構築は行う。

/docker-entrypoint-initdb.d/ に保存されたユーザ定義の初期化スクリプトを起動時に実行する(初期tableデータ作成などに利用)

我可以理解这样的行为。

Docker Compose 可以使用

docker-compose 是一个文件,用于将多个容器组合成一个应用程序并定义其配置。
为了更好地理解,我们将通过使用docker-compose构建一个简单的应用程序来解释这一过程。

创建应用程序

想象一个简单的两层架构应用程序。前端使用PHP运行的httpd服务器,连接到MySQL数据库。PHP连接到MySQL,计算用户请求的总次数,并将其保存到数据库中。用户将看到计数器的值,并且数据库会持久保存该计数器信息。

User <-−80--> HTTPD w/PHP <--3306--> MySQL

组成应用程序的文件集合

./app
./app/counter.php
./mysql
./mysql/init
./mysql/init/init.sql
./mysql/data
./htdocs
./docker-compose.yml
./build
./build/phpapp
./build/phpapp/Dockerfile

docker-compose.yml 的内容如下

version: "2"
services:
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    volumes:
      - "./mysql/init:/docker-entrypoint-initdb.d"
      - "./mysql/data:/var/lib/mysql"
    environment:
      - MYSQL_ROOT_PASSWORD=secret
    command: --innodb-use-native-aio=0
  phpapp:
    image: phpapp
    build: ./build/phpapp
    volumes:
      - "./app:/var/www/html"
    ports:
      - "8080:80"

由于在Windows环境下有必要运行,因此添加了参数”services.mysq.command: –innodb-use-native-aio=0″(2020.9.2)。

这个docker-compose文件包含以下架构的”规范”。

    • このシステムは2つのコンテナ(サービス)で構成されそれぞれ “mysql”、”phpapp” という名称とする。

 

    • “mysql”サービスはDocker Hubの mysql:5.7 というimageを利用する

 

    • “phpapp”サービスはphpappというimageを利用する。そのimageは ./build/phpapp/Dockerfile を利用して作成されたものを利用する

 

    • “mysql” コンテナは ./mysql/initディレクトリを /docker-entrypoint-initdb.d にマウントする。 mysqlイメージの仕様からそこにある init.sql がコンテナ作成時に実行される

 

    • “mysql” コンテナは ./mysql/dataディレクトリを /var/lib/mysql にマウントする。これによりコンテナ内のMySQLデータはmac上で管理されそれは永続化される

 

    • MySQLのROOTパスワードを指定する

 

    • “phpapp”コンテナは./appを /var/www/htmlにマウントする. app内のファイルはphp実行ファイルでありhttpd上で動作するアプリケーションとなる

 

    “phpapp”の80ポートはmac上の8080ポートにバインドする。

请记下每个文件的内容如下。

鉴于对Dockerfile中无需使用EXPOSE进行说明的指导,我们已将其删除。(2021.8.18)

FROM centos

RUN yum update -y \
    && yum install httpd php php-mysql php-pdo -y \
    && echo "Hello from httpd" > /var/www/html/index.html \
    && echo "<?php phpinfo(); " > /var/www/html/index.php \
    && yum clean all

ENTRYPOINT ["/usr/sbin/httpd", "-DFOREGROUND"]

phpapp的Dockerfile与之前的httpd创建的Dockerfile类似。不同的是,在phpapp的Dockerfile中还安装了与php及其连接到mysql的驱动程序(php php-mysql php-pdo)相关的组件。

CREATE DATABASE IF NOT EXISTS test;
CONNECT test;

CREATE TABLE IF NOT EXISTS counter (
    id INT AUTO_INCREMENT PRIMARY KEY,
    create_at TIMESTAMP
);

这是用于MySQL应用程序的表定义。它是一个简单的用于记录访问的表。

<?php
    ini_set( 'display_errors', 1 );
    date_default_timezone_set('Asia/Tokyo');

    $pdo = new PDO(
        'mysql:dbname=test;host=mysql;charset=utf8mb4',
        'root',
        'secret'
    );

    $stmt = $pdo->prepare("INSERT INTO counter () VALUE ()");
    $stmt->execute();

    $stmt = $pdo->prepare("SELECT * FROM counter ORDER BY id DESC limit 1");
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    print_r($row);

?>

在用户访问的HTTPD上运行的PHP应用程序。它连接到MySQL并记录和获取表的访问。

值得一提的是,在PDO中的host=mysql部分。使用docker-compose启动的每个容器都可以在可以相互解析IP的网络内以其分配的服务名称作为主机名启动。

启动/停止Docker Compose

在放置docker-compose.yml的目录中执行以下命令。

$ docker-compose up -d
Starting app_phpapp_1 ... done
Starting app_mysql_1  ... done

如果按照先前的步骤进行,可以认为mysql:5.7镜像已经在DockerHub上安装完毕,首先会创建phpapp镜像。

当启动完成后,您可以在Mac上的浏览器中通过 http://localhost:8080/counter.php 进行确认,可以看到每次刷新都会增加计数的应用程序。

undefined

停止将在下面进行。

$ docker-compose down
Stopping app_mysql_1  ... done
Stopping app_phpapp_1 ... done
Removing app_mysql_1  ... done
Removing app_phpapp_1 ... done
Removing network app_default```

当再次启动时,可以看到从上次计数器加1后显示的值,并且MySQL数据也被持久化。

如果要进入正在运行的容器,请指定以下服务名称即可,无需使用”-it”参数。

$ docker-compose exec mysql /bin/bash
root@ad984396ba7f:/#
root@ad984396ba7f:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.22 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.04 sec)
mysql> connect test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Connection id:    5
Current database: test

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| counter        |
+----------------+
1 row in set (0.00 sec)

mysql> select * From counter;
+----+---------------------+
| id | create_at           |
+----+---------------------+
|  1 | 2018-05-26 06:57:47 |
|  2 | 2018-05-26 06:57:48 |
|  3 | 2018-05-26 06:57:49 |
|  4 | 2018-05-26 06:57:52 |
|  5 | 2018-05-26 07:03:58 |
+----+---------------------+
5 rows in set (0.00 sec)

mysql>

最后

我试着用容易理解的方式来解释Docker和Docker Compose的基本概念。通过这些工具,你能够体验到系统(服务)如何通过代码来进行管理,包括架构的管理。这样一来,对于那些不太了解Docker的人来说,或对于没有具体应用想法的人来说,希望这能够提供一些帮助。

我把技术类的文章投稿地点转移到了我的个人博客上。我正在努力在初学者友好、包括AWS等广泛的技术领域投稿文章,如果方便的话,请也参考这里!

广告
将在 10 秒后关闭
bannerAds