Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9299

自分がDockerについて調べて、やっと使えるようになった気がした手順

$
0
0
初めに 環境をコンテナ化、各々の開発環境や、開発環境と実行環境の差異をなくす、開発が爆速化など、dockerに関することを目にするのですが、恥ずかしながら私はdockerの取っ掛かりにとても苦労しました。Qiitaの記事、書籍を調べ、ようやっと、なんとなくつかめた気がする、という段階です。もし同様の方が見えて、当記事がほんの少しでも助けになったら、とてもうれしいです。 環境 Windows10 Home 20H2 WSL2インストール済み Docker Desktop for Windows VSCode 当記事でやること Node.js用のコンテナ、SQLServer用のコンテナを建てる TypeScriptを用いる ブラウザからNode.jsコンテナにアクセス Node.jsコンテナからSQLServerコンテナに接続し、データを取得しブラウザに表示させる なぜSQLServerなのか 当方が本業で使っているのがSQLServerであり、慣れているためです。しかし、個人で無料で開発や学習を進めるにはハードルが高いと感じ、これからはPostgreSQLに切り替えようと考えています。話はそれますが、学習のためにSQLServer Azureを建てたのですが、無料期間が切れたことが気づかず、ただのテストデータがあるだけで、1500円ほどクレジットカードから引き落とされたことがあります。今思えば、15万円でも、1万5千円でもなく、1500円でよかったです。 当記事で心がけていること 理屈よりも、手順を踏めば、同じように動く 体験後は、コンテナを廃棄し、当手順を踏む前の状態に戻す 以上を心がけています。 参考にさせて頂いた記事、サイト 【Node.js】 Dockerを用いてNode.js Express MySQLの環境を構築するまでの道のり - Qiita Get started Express + TypeScript する - Qiita [Node.js] Express を TypeScript で書く - 環境整備まで - Qiita DockerコンテナでSQLServerを動かす方法 | ばったんの技術系ブログ 【連載】WSL2、Visual Studio Code、DockerでグッとよくなるWindows開発環境 〜 その1:まずは概要 〜 | SIOS Tech. Lab 【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その1:コンテナってなに? 〜 | SIOS Tech. Lab いつから始めるの?Docker、AWS、kubernetes初学者がこっそり1日で先輩に追いつく3つの作戦 - YouTube Docker:SQL Server on Linux 用のコンテナーのインストール - SQL Server | Microsoft Docs 実践 事前の状態の確認 下記コマンドを実行し状態を確認します。 1. Dockerイメージを一覧する。 docker images # 結果 REPOSITORY TAG IMAGE ID CREATED SIZE コンテナを一覧する。 docker ps -a # 結果 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES プロジェクトフォルダを作る エクスプローラーにて、任意の場所にdocker-sqlserverというフォルダを作成します。 例)D:\data\docker-sqlserver ※フォルダ名は任意で構いません。 docker-compose.yml (プロジェクトフォルダ)\docker-compose.ymlを作成します。 docker-compose.yml version: '3' services: apply: build: . container_name: webserver ports: - '3000:3000' working_dir: /app volumes: - ./src:/app command: npm start database: image: mcr.microsoft.com/mssql/server:2017-latest container_name: sql2017 ports: - 1433:1433 environment: - ACCEPT_EULA=Y - SA_PASSWORD=<YourStrongP@ssw0rd> - MSSQL_COLLATION=Japanese_CI_AS volumes: - ./database/data:/var/opt/mssql/data - ./database/data:/var/opt/mssql/log - ./database/secrets:/var/opt/mssql/secrets 注意 字下げ部分、タブ(\t)だと、のちのコマンド実行時エラーが発生しました。 スペース2つを用います。 Node.jsコンテナに必要なパッケージをインストールする VSCodeのターミナル画面でコマンドを実行します。 docker compose run --rm apply /bin/bash VSCodeのターミナルの表示が以下のようになります。 "root@ae71187cc460:"の部分は、異なる表示になると思います。 root@ae71187cc460:/app# イメージ、コンテナの確認(スキップしてもよい手順です) PowerShellを開き(もしくはVSCodeで別のターミナルを開き)、Dockerイメージ、Dockerコンテナを一覧します。 # イメージを一覧するコマンドを実行します。 docker images # 結果 REPOSITORY TAG IMAGE ID CREATED SIZE docker-sqlserver_apply latest 81fe3ebc1b85 4 weeks ago 943MB # コンテナを一覧するコマンドを実行します。 docker ps # 結果 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 07bd2e4fdc83 docker-sqlserver_apply "docker-entrypoint.s…" 30 minutes ago Up 30 minutes docker-sqlserver_apply_run_ec19ff4eaa38 コンテナに入った状態になり、コマンドを入力し実行すると、ホストであるWindowsではなく、コンテナに対する操作になります。 以下の順でコンテナ内でコマンドを実行します。 # packages.jsonを初期化します。(package.jsonが作成されます。) npm init -y # パッケージをインストールします。 npm install --save express npm install --save tedious # 開発に必要なパッケージをインストールします。 npm install --save-dev typescript npm install --save-dev @types/express npm install --save-dev @types/tedious npm install --save-dev nodemon npm install --save-dev ts-loader npm istanll --save-dev webpack npm install --save-dev webpack-cli npm install --save-dev webpack-node-externals # 以下のように列挙して実行も可能です。 npm install --save express tedious npm install --save-dev typescript @types/express ...... ホストPC側のプロジェクトフォルダの.srcフォルダにpackage.json、node_modulesフォルダが作成され、必要なファイルがダウンロードされます。 ./src/package.jsonを確認します。 ./src/package.json { "name": "app", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1", "tedious": "^11.0.9" }, "devDependencies": { "@types/express": "^4.17.12", "@types/tedious": "^4.0.3", "nodemon": "^2.0.7", "ts-loader": "^9.2.3", "typescript": "^4.3.2", "webpack": "^5.39.0", "webpack-cli": "^4.7.2", "webpack-node-externals": "^3.0.0" } } ./src/package.jsonのscriptsにコマンドを登録します。 ./src/package.json { ... "scripts": { "build": "webpack --config webpack.config.js", "dev": "nodemon -L", "start": "node ./dist/server.js", "test": "echo \"Error: no test specified\" && exit 1" } ... } TypeScriptをトランスパイルするための環境を整えます。 tsconfig.json { "compilerOptions": { "sourceMap": true, "noImplicitAny": true, "module": "es2015", "target": "es2017", "jsx": "react", "lib": ["es2018", "dom"], "moduleResolution": "node", "removeComments": true, "strict": true, "noUnusedLocals": false, "noUnusedParameters": false, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "strictFunctionTypes": false } } webpack.config.js const path = require('path'); const nodeExternals = require('webpack-node-externals'); module.exports = { mode: 'development', target: 'node', externals: [ nodeExternals() ], devtool: 'eval-source-map', module: { rules: [ { loader: 'ts-loader', test: /\.ts$/, exclude: [/node_modules/], options: { configFile: 'tsconfig.json'} } ] }, resolve: { extensions: ['.ts', '.js', '.json'] }, entry: './src/server.ts', output: { filename: 'server.js', path: path.resolve(__dirname, 'dist') }, node: { __dirname: false } }; nodemon.json { "watch": [ "dist" ], "ext": "ts, js, json", "exec": "node ./dist/server.js" } サーバサイドのメインプログラムをコーディングします。 ./src/src/server.ts import * as Express from 'express'; const app = Express(); app.get('/', (req: Express.Request, res: Express.Response, next: Express.NextFunction) => { res.send('アクセス成功'); }); const portNo = process.env.PORT || 3000; app.listen(portNo, () => { console.log(`app running on port ${portNo}.`); }); export default app; コンテナ内でトランスパイルを実行します。 # トランスパイル実行 npm run build # 結果 成功すると以下のような表示になります。 > app@1.0.0 build /app > webpack --config webpack.config.js asset server.js 6.08 KiB [emitted] (name: main) runtime modules 937 bytes 4 modules built modules 319 bytes [built] ./src/server.ts 277 bytes [built] [code generated] external "express" 42 bytes [built] [code generated] webpack 5.39.0 compiled successfully in 17709 ms トランスパイル実行後、ホストPCのプロジェクトフォルダに、./src/dist/server.jsが生成されています。 コンテナ内でNode.jsサーバの実行をテストします。 # 実行 npm start # 結果 > app@1.0.0 start /app > node ./dist/server.js app running on port 3000. ブラウザでhttp://localhost:3000にアクセスします。 当方、この段階でブラウザで接続できると思っていたのですが、設定したHost側のport:3000がコンテナ側のport:3000と結びつかないらしく、ブラウザでlocalhost:3000に接続しても、(この段階では)アクセスできませんでした。 Node.js用コンテナに必要な初期ファイルがそろったので、いったんコンテナを抜けます。 当コンテナは削除されます。 exit コンテナ一覧の確認(スキップしてもよい手順です) # コンテナを一覧するコマンドを実行する。-aは、停止中のコンテナも一覧するオプション。 docker ps -a # 結果 先ほどはリストアップされていたコンテナが削除されています。 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 本番(開発の本番用という意味の本番です)コンテナを作成します。 ホストPCのプロジェクトフォルダのパスで以下のコマンドを実行します。 # コンテナの作成と実行を行います。 docker compose up # ※-dオプションを使用すると、バックグラウンドで実行します。しかし当方、実行状況が確認しやすいため、-dオプション使用せずに実行するほうが好みです。 docker compose up -d SQLServerのファイル大きいため、ダウンロードに数分ようすると思います。 また、以降SQLServerのコンテナを開始するときも、当方の環境では2分弱要します。 コンテナ一覧の確認(スキップしてもよい手順です) # 稼働中のコンテナを一覧 docker ps # 結果 webserverというコンテナ名のNode.jsコンテナと、sql2017というコンテナ名のデータベースコンテが作成されています。 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e5efb3c4f84f 78e2d1575743 "/opt/mssql/bin/nonr…" 20 minutes ago Up 20 minutes 0.0.0.0:1433->1433/tcp, :::1433->1433/tcp sql2017 404a4e158144 81fe3ebc1b85 "docker-entrypoint.s…" 20 minutes ago Up 20 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp webserver SQLServerにデータベースとテーブルを作成します。 SQLServerコンテナに入ります。 docker exec -it sql2017 /bin/bash # 表示が以下のようになります。"root@e5efb3c4f84f"の部分は各々異なる表示になると思います。 root@e5efb3c4f84f:/# SQLSserverのCLIツールsqlcmdを起動し、データベースの作成、テーブルの作成、レコードの挿入を行います。 - 作成するデータベース、テーブル データベース:testdb テーブル: user フィールド名 型 id smallint name nvarchar(20) 以下はSQLServerコンテナ内でのコマンドです。 # CLIツールを起動します。 /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "<YourStrongP@ssw0rd>" # 表示が以下のようになります。 1> # データベースを作成します。 CREATE DATABASE TestDB GO # テーブルを作成します。 CREATE TABLE TestDB.dbo.users (id smallint, name nvarchar(20)) GO # レコードを挿入します。 INSERT INTO TestDB.dbo.users (id, name) VALUES (1, '山田 太郎'), (2, '山田 花子') GO # 挿入したレコードを確認します。(スキップしてもよい手順です) SELECT * FROM TestDB.dbo.users GO # 結果 以下のように表示されます。 id name ------ -------------------- 1 山田 太郎 2 山田 花子 (2 rows affected) # CLIツールを終了します。 exit Node.js側に、SQLServerに接続し、データを取得し、表示させるコードを作成します。 ./src/src/routes/db-connect.ts import * as Express from 'express'; import * as Tedious from 'tedious'; const router = Express.Router(); router.get('/', async (req: Express.Request, res: Express.Response, next: Express.NextFunction) => { const getConnection = (): Promise<Tedious.Connection> => { return new Promise<Tedious.Connection>((resolve, reject) => { const config: Tedious.ConnectionConfig = { server: 'sql2017', //コンテナ名で接続します。 authentication: { type: 'default', options: { userName: 'sa', password: '<YourStrongP@ssw0rd>' } }, options: { port: 1433, trustServerCertificate: true } }; const conn = new Tedious.Connection(config); conn.connect(); conn.on('connect', (err) => { if (err) { return reject(err); } return resolve(conn); }); }); } const executeStatement = (conn: Tedious.Connection): Promise<{key: string, value:any}[]> => { return new Promise((resolve, reject) => { const request = new Tedious.Request('SELECT * FROM testdb.dbo.users', (err: Error) => { if(err){ return reject(err); } return resolve(rows); }); const rows: {key: string, value: any}[] = []; request.on('row', (columns: Tedious.ColumnValue[]) => { const row:any = {}; columns.forEach(column => { row[column.metadata.colName] = column.value; }); rows.push(row); }); conn.execSql(request); }); } try { const conn = await getConnection(); const result = await executeStatement(conn); res.send(JSON.stringify(result)); } catch(err) { res.send(err); } }); export default router; サーバサイドのメインプログラムを修正します。 ./src/src/server.ts import * as Express from 'express'; import dbConnect from './routes/db-connect'; //←追記 const app = Express(); app.use('/db-connect', dbConnect); //←追記 app.get('/', (req: Express.Request, res: Express.Response, next: Express.NextFunction) => { res.send('アクセス成功'); }); //…以下略 Node.jsコンテナでトランスパイルします。 npm run build ブラウザでhttp://localhost:3000/db-connectにアクセスし、以下のような表示になれば成功です。 [{"id":1,"name":"山田 太郎"},{"id":2,"name":"山田 花子"}] Node.jsコンテナからSQLServerコンテナに接続し、データを取得し、ブラウザに返しています。 当方、ここまで来たとき、少々感動しました。 後片付け コンテナの停止 # docker compose up (-dオプションなし)でコンテナを開始していた場合、そのコマンドを実行したターミナルでctrl+cを押すとコンテナが停止します。 # dockuer compose up -d でコマンドを開始した場合、以下のコマンドでコンテナを停止させます。 docker compose stop コンテナの削除 コマンド "docker rm (コンテナ名もしくはコンテナID)" を実行し、コンテナを削除します。 # Node.jsコンテナを削除します。"webserver"はコンテナ名です。 docker rm webserver # SQLServerコンテナを削除します。"sql2017"はコンテナ名です。 docker rm sql2017 イメージの削除 コマンド docker rmi (イメージID) を実行し、イメージを削除します。 # イメージIDを確認するため、イメージを一覧します。 docker images # 削除するイメージIDを確認します。 REPOSITORY TAG IMAGE ID CREATED SIZE docker-sqlserver_apply latest 81fe3ebc1b85 5 weeks ago 943MB # イメージを削除します。 docker rmi 81fe3ebc1b85 以上

Viewing all articles
Browse latest Browse all 9299

Trending Articles