让我们深入了解 Docker。用docker构建web服务器。我们正在计划开发JavaScript API,建立MySQL数据库,并创建一个 PHP 网站使用 API 服务。Php + Node.js + Mysql — DockerSeries — Episode#1
我们要构建的容器,是三个独立的容器组成,它们三者构成一个网络。
以下是目录结构和相应的步骤:
这是最终结果:http://localhost:8888/
准备好练习了吗?
1#Step — 在 Ubuntu 上安装并运行 Docker Desktop。如果需要,您可以参考这篇文章;
2#Step — 使目录结构(复制/粘贴并按回车键,您就可以进入VScode:)
mkdir docker
cd docker
mkdir proj_01
cd proj_01
mkdir api
cd api
mkdir db
mkdir src
cd ..
mkdir website
cd website
mkdir vendor
cd ..
code .
3#Step — 进入 VScode 后,让我们创建一个 Dockerfile:
转到: :proj_01/api/db/Dockerfile
FROM mysql
ENV MYSQL_ROOT_PASSWORD jaythree
4#Step — 让我们构建映像。
返回到根目录并在终端中键入:proj_01/
docker build -t mysql-image -f api/db/Dockerfile .
你会得到这个:/ERROR
无法在 unix:///home/j3/.docker/desktop/docker.sock 连接到 Docker 守护程序。docker 守护程序是否正在运行?
哎呀!运行 Docker 桌面,您就可以开始了!
请立即运行 Docker 桌面!
返回根目录 ~/docker/proj_01$ 并尝试再次构建 MySQL 镜像...巨大的成功!
5#Step — 使用我们最近生成的映像运行 MySQL 容器。转到 &类型:proj_01/
容器 # 1
docker run -d -v $(pwd)/api/db/data:/var/lib/mysql --rm --name mysql-container mysql-image
在 Docker 桌面中,您将看到 MySQL 容器运行良好!
6#Step — 现在我们已经启动并运行了一个 MySQL 容器,让我们创建一个数据库 (outfit_db),定义一个表(产品),并插入一些值。
对于此测试,我们将使用我们在服装商店的在线数据库:
DB来自这篇文章。我们现在只使用三行...
创建此文件:
proj_01/db/script.sql
CREATE DATABASE IF NOT EXISTS outfit_db;
USE outfit_db;
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT,
sales_code INT NOT NULL,
date date NOT NULL,
store_id VARCHAR(255),
product VARCHAR(255),
qty INT NOT NULL,
unit_price DECIMAL(10, 2),
PRIMARY KEY (id)
);
INSERT INTO products VALUE(0, 65014, '2019-01-12', 'Shopping Morumbi', 'Aster Pants', 5, 114);
INSERT INTO products VALUE(0, 65014, '2019-01-12', 'Shopping Morumbi', 'Trench Coat', 1, 269);
INSERT INTO products VALUE(0, 65016, '2019-01/-2', 'Iguatemi Campinas', 'Peter Pan Collar', 2, 363);
7#Step —让我们执行数据库和表,并使用前面的脚本用值填充它。转到 :proj_01/
docker exec -i mysql-container mysql -uroot -pjaythree < api/db/script.sql
8#Step — 现在,让我们访问容器以执行 SQL 选择。
若要查看容器中的表并使用命令行与数据库交互,需要通过调用方法访问它:outfit_db
exec
docker exec -it mysql-container /bin/bash
bash-4.4# mysql -uroot -pjaythree
mysql> USE outfit_db;
mysql> SELECT * FROM products;
exit
exit
具体来说,它使用该命令与名为 的 Docker 容器进行交互。命令末尾的 指示它正在指定容器内启动交互式 b灰壳 (CLI) 会话。这允许您访问容器的文件系统并在其中工作,并像在容器本身中一样运行命令。这是在 Docker 容器中执行任务或维护操作的常用方法。docker exec
mysql-container
/bin/bash
为方便起见,以下是我们在终端中执行的上述两项操作:
$ docker exec -i mysql-container mysql -uroot -pjaythree < db/script.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
$ docker exec -it mysql-container /bin/bash
bash-4.4# mysql -uroot -pjaythree
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 8.1.0 MySQL Community Server - GPL
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
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> USE outfit_db;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> SELECT * FROM products;
+----+------------+------------+-------------------+------------------+-----+------------+
| id | sales_code | date | store_id | product | qty | unit_price |
+----+------------+------------+-------------------+------------------+-----+------------+
| 1 | 65014 | 2019-01-12 | Shopping Morumbi | Aster Pants | 5 | 114.00 |
| 2 | 65014 | 2019-01-12 | Shopping Morumbi | Trench Coat | 1 | 269.00 |
| 3 | 65016 | 2019-01-02 | Iguatemi Campinas | Peter Pan Collar | 2 | 363.00 |
+----+------------+------------+-------------------+------------------+-----+------------+
3 rows in set (0.00 sec)
mysql> exit
Bye
bash-4.4# exit
exit
注意:如果需要删除,请使用:mysql> DROP DATABASEoutlet_db;
9#Step — 继续通过终端安装Node(NodeJs官网),因此输入以下命令:
sudo apt install npm
node -v
v18.13.0
10#Step — GoTo & type:
proj_01/api/
:
npm init
这是我们终端的输出:
~/docker/proj_01/api$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install ` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (api)
version: (1.0.0)
description: Docker intro
entry point: (index.js)
test command: test
git repository:
keywords: Docker
author: j3
license: (ISC)
About to write to /home/j3/docker/proj_01/api/package.json:
{
"name": "api",
"version": "1.0.0",
"description": "Docker intro",
"main": "index.js",
"scripts": {
"test": "test"
},
"keywords": [
"Docker"
],
"author": "j3",
"license": "ISC"
}
Is this OK? (yes)
该命令用于初始化新的 Node.js 项目。当您在终端中运行此命令时,它会提示您一系列问题,并询问各种配置选项来设置您的项目。这些问题通常包括项目名称、版本、说明、入口点文件、测试命令等内容。npm init
回答这些问题或接受默认值后,npm 将在项目目录中生成一个文件。此文件对于管理 Node.js 应用程序的依赖项、脚本和其他与项目相关的元数据至关重要。它会跟踪项目的依赖项及其版本,从而更轻松地在不同系统上共享和重现项目。package.json
package.json
总之,是一个命令,可帮助您为 Node.js 项目创建和配置文件,从而更轻松地管理依赖项和项目设置。npm init
package.json
11#Step — 让我们安装 。现在运行在 :nodemon
proj_01/api/
npm install --save-dev nodemon
or
npm install -D nodemon
npm fund
我们提到的两个命令执行以下操作:
npm install --save-dev nodemon
:此命令将包安装为 Node.js 项目的开发依赖项。 是一个实用程序,用于监视 Node.js 应用程序文件中的更改,并在检测到更改时自动重新启动服务器。该标志指定应添加到文件部分的标志。这通常用于仅在开发和测试期间(而不是在生产中)需要的工具和依赖项。nodemon
nodemon
--save-dev
nodemon
devDependencies
package.json
npm fund
:此命令用于显示有关项目中使用的文件包的资金选项的信息。它显示了有关如何在经济上支持您所依赖的软件包的维护者的信息。这是一种鼓励用户为开源项目做出贡献的方式,如果维护者已经设置了资金选项或捐赠平台的链接。-D
npm install -D nodemon
这两个命令(或)都将正确地将nodemon安装为开发依赖项,并相应地更新您的package.json文件。--save-dev
-D
总之,第一个命令作为开发依赖项安装,这对于开发目的很有用,第二个命令用于检查与项目中使用的包相关的资金信息。nodemon
这是我们的终端:
~/docker/proj_01/api$ npm install - save-dev nodemon
added 35 packages, and audited 36 packages in 5s
3 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
~/docker/proj_01/api$ npm fund
[email protected]
└─┬ https://opencollective.com/nodemon
│ └── [email protected]
└─┬ https://paulmillr.com/funding/
│ └── [email protected]
└── https://github.com/sponsors/jonschlinkert
└── [email protected]
12#Step — 让我们安装和驱动程序。转到 :express
MySQL
proj_01/api/
npm install --save express mysql
该命令用于安装两个 Node.js 包和 ,并将它们另存为项目中的依赖项。npm install --save express mysql
express
mysql
express
:这个流行的 Node.js Web 应用程序框架简化了 Web 应用程序和 API 的构建。它提供了用于路由、处理 HTTP 请求和响应、中间件支持等的工具和功能。通过安装它并将其另存为依赖项(标志现已弃用,因此对于现代 npm 版本不是必需的),您可以包含在项目中,使其可用于代码。请参阅官方 NPM 文档。--save
express
mysql
:这是 MySQL 数据库的 Node.js 驱动程序。它允许您的 Node.js 应用程序与 MySQL 数据库交互,使您能够执行数据库操作,例如查询、插入、更新和删除数据。通过安装并另存为依赖项,您可以在项目中使用它来连接和使用 MySQL 数据库。mysql
因此,该命令会安装这两个包并将它们添加到文件中的项目部分,从而允许您在 Node.js 应用程序中使用它们。npm install --save express mysql
dependencies
package.json
13#Step —转到该文件并将以下代码添加到脚本部分中:proj_01/api/package.json
,
"start": "nodemon ./src/index"
整个文件的结果如下:
proj_01/api/package.json
{
"name": "api",
"version": "1.0.0",
"description": "Docker intro",
"main": "index.js",
"scripts": {
"test": "test",
"start": "nodemon ./src/index"
},
"keywords": [
"Docker"
],
"author": "j3",
"license": "ISC",
"dependencies": {
"-": "^0.0.1",
"express": "^4.18.2",
"mysql": "^2.18.1",
"nodemon": "^3.0.1",
"save-dev": "^0.0.1-security"
}
}
在文件中,该部分用于定义可以使用 npm 执行的各种脚本或命令。此代码块定义了两个脚本:package.json
"scripts"
"test": "test"
:此脚本名为“test”,它与命令“test”相关联。此脚本的实际功能取决于它在项目中的实现方式。在许多 Node.js 项目中,“test”脚本用于运行自动化测试,例如使用 Mocha、Jest 等测试框架编写的测试。“test”脚本的特定行为应记录在项目的自述文件或单独的测试配置文件中。"start": "nodemon ./src/index"
:此脚本名为 ,它与命令 相关联。当您在终端中运行时,它将执行此处指定的命令,即 。此命令使用该工具通过运行位于 的文件来启动 Node.js 应用程序。 是一个实用程序,每当在指定文件中检测到更改时,它都会自动重新启动 Node.js 应用程序,这在开发过程中非常有用,可以在您进行代码更改时自动刷新服务器。start
nodemon ./src/index
npm start
nodemon ./src/index
nodemon
./src/index
nodemon
因此,总而言之,这些脚本定义了可以使用 npm 执行的命令。 通常用于运行测试,通常用于启动 Node.js 应用程序,通常在开发期间通过 自动重新加载。"test"
"start"
nodemon
14#Step —请建立一个目录并将文件放在其中:/api/src
index.js
proj_01/api/src/index.js
const express = require('express');
const mysql = require('mysql');
const app = express();
const connection = mysql.createConnection({
host: 'mysql-container', //'172.17.0.2', You can streamline this operation by employing the alias 'mysql-container' when executing the Docker run command with the addition of '--link mysql-container.'
user: 'root',
password: 'jaythree',
database: 'outfit_db',
insecureAuth: true // Add this line
});
connection.connect();
app.get('/products', function(req, res) {
connection.query('SELECT * FROM products', function (error, results) {
if (error) {
throw error
};
res.send(results.map(item => ({ name: item.product, price: item.unit_price })));
});
});
app.listen(9001, '0.0.0.0', function() {
console.log('Listening on port 9001');
})
注意:要获取 IP 地址:docker inspect mysql-container
此指令将生成一组与指定容器相关的大量 JSON 格式的详细信息。我们的目标是使用以下格式查找网络 IP: “IPAddress”: “172.17.0.2”
15#Step —生成一个 Dockerfile 来设置 Node.js 应用程序:
proj_01/api/Dockerfile
FROM node:18-slim
WORKDIR /home/node/app
CMD npm start
此 Dockerfile 定义了为 Node.js 应用程序创建 Docker 容器的指令:
node:18-slim
/home/node/app
npm start
package.json
总体而言,此 Dockerfile 设置了一个运行 Node.js 应用程序的环境,将应用程序文件放在指定的目录中,并在启动容器时使用“npm start”启动应用程序。
16#Step — 让我们为 Node.js 应用程序构建一个映像。
转到:proj_01/
docker build -t node-image -f api/Dockerfile .
这是我的终端:
j3@JAYTHREE:~/docker/proj_01$ docker build -t node-image -f api/Dockerfile .
[+] Building 2.5s (6/6) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 91B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/node:18-slim 2.4s
=> [1/2] FROM docker.io/library/node:18-slim@sha256:e5c8c319295f6cbc288e19506a9ac37afa3b330f4e38afb01d1269b579cf6a5b 0.0s
=> CACHED [2/2] WORKDIR /home/node/app 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9edd82ba69b8e912e3f0e3ef876a14bb4f5a82f8b19b8bbeaa612cb1e642ae0e 0.0s
=> => naming to docker.io/library/node-image 0.0s
What's Next?
View summary of image vulnerabilities and recommendations → docker scout quickview
17#Step — 现在在以下位置运行节点容器:proj_01/
容器 # 2
docker run -d -v $(pwd)/api:/home/node/app -p 9001:9001 --link mysql-container --rm --name node-container node-image
该标志用于指定端口映射。-p
以下是在此上下文中执行的操作:-p
-p 9001:9001
:此标志将主机上的端口映射到 Docker 容器内的端口。在本例中,它将主机上的端口 9001 映射到容器内的端口 9001。定向到主机上端口 9001 的任何流量都将转发到容器的端口 9001。--link
当您在侦听特定端口的 Docker 容器中运行服务,并且您希望从主机访问该服务时,通常会使用此方法。通过指定此端口映射,可以与容器中运行的服务进行交互,就像它直接在主机上运行一样。
因此,在此特定示例中,对主机上的端口 9001 发出的任何请求都将转发到在名为 的 Docker 容器内运行的 Node.js 应用程序。node-container
18#step — 如果您打开 Web 浏览器并导航到 ,它将断言:http://localhost:9001/
不:/
转到您的 Docker 桌面终端 在选项卡中,您将看到以下内容:/Logs
错误:ER_NOT_SUPPORTED_AUTH_MODE:客户端不支持服务器请求的身份验证协议;考虑升级 MySQL 客户端
此问题已在 StackOverflow 上的此线程中得到解决。
解决方案:请重复步骤#8,一旦进入MySQL容器的终端,输入以下命令:
ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'jaythree';
or
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
flush privileges;
exit
在 Docker 桌面选项卡内,请运行这些脚本 ️ 终端
19#step — 在 Docker Desktop 中停止并重新初始化此容器。
按以下顺序刷新两个容器,方法是单击按钮:Restart
重新启动 mysql 容器并...
重新启动节点容器。
20#step — 现在导航到:
http://localhost:9001/products
瞧!您的 API 已启动并平稳运行,并按预期响应!
21#step — 让我们继续创建一个 PHP 应用程序,该应用程序将与该 API 交互并使用该 API。
转到:
proj_01/website/index.php
Docker Intro | Jungletronics
Inspirational Clothing and Fashion Catalogue:
Product
Price
product; ?>
unit_price; ?>
22#step — 为您的 PHP 应用程序创建另一个 docker 文件:
proj_01/website/Dockerfile
FROM php:7.2-apache
WORKDIR /var/www/html
23#step — 在其上构建映像app_01/:
docker build -t php-image -f website/Dockerfile .
24#step — 运行 php 容器:
容器 # 3
docker run -d -v $(pwd)/website:/var/www/html -p 8888:80 --link node-container --rm --name php-container php-image
25#step —浏览至:
http://localhost:8888/
26#step - 启用引导程序以增强网页的外观。
下载适用于 Bootstrap v5.0.2 的即用型编译代码,轻松放入您的项目中。
请点击提供的链接下载ZIP文件。下载后,提取其内容,然后将解压缩的文件夹重命名为 .bootstrap
将文件保存在目录中。proj_01/website/vendor
27#step — 转到并在 app_01/website/index.php
28#step — 在 Docker Desktop 中访问 MySQL 容器的终端并引入新产品。观察此添加是否同时反映在 API 和网站中。
29#step — 创建一个 Docker 组合:
proj_01/docker-compose.yml
version: "3.7"
services:
db:
image: mysql-image
container_name: mysql-container
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: jaythree
volumes:
- ./api/db/data:/var/lib/mysql
restart: always
api:
build: ./api
container_name: node-container
restart: always
volumes:
- ./api:/home/node/app
ports:
- "9001:9001"
depends_on:
- db
web:
image: php-image
container_name: php-container
restart: always
volumes:
- ./website:/var/www/html
ports:
- "8888:80"
depends_on:
- db
- api
要达到预期的结果,只需执行:,就像魔术一样,一切都将被配置!docker-compose up -d
给你!
如果你也有兴趣学习Python,请考虑查看这篇文章。非常感谢您的关注!
我相信这篇文章为您提供了有关 Docker 的更多见解。