この記事に見られるように、Dockerコンテナーでホストしたいノードアプリケーションがあります。
https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
ただし、私のプロジェクトでは、ソースを直接実行することはできません。ES6やTypeScriptからコンパイルする必要があります。私はgulpを使用してbabel、browserify、およびtsifyでビルドします。ブラウザーとサーバーのセットアップは異なります。
この場合、Dockerイメージの構築および自動化に最適なワークフローは何ですか?そのようなワークフローを説明するWeb上のリソースはありますか? Dockerimageはnpm install
またはこれをすべて行うためにシェルスクリプトを作成し、Dockerfileにすべてをまとめてパックする必要がありますか。
Dockerfileがビルドを実行する必要がある場合-イメージにはすべてのdev依存関係が含まれている必要がありますが、これは理想的ではありませんか?
注:Dockerコンテナーをセットアップして実行できましたが、これにはすべてのファイルを事前にインストールしてビルドする必要がありました。
考えられる解決策の1つは、ビルド手順を特別なdockerイメージでラップすることです。多くの場合、Builder imageと呼ばれます。 nodejs、npm、gulp、babel、tscなど、すべてのビルド依存関係が含まれている必要があります。すべてのビルドプロセスをカプセル化し、ホストにこれらのツールをインストールする必要がなくなります。
最初にビルダーイメージを実行し、ソースコードディレクトリをボリュームとしてマウントします。同じまたは別のボリュームを出力ディレクトリとして使用できます。最初のイメージはコードを取得し、すべてのビルドコマンドを実行します。
最初のステップとして、ビルドしたコードを使用して、今と同様に実動ドッカーイメージにパックします。
TypeScriptのdocker builderイメージの例を次に示します。 https://hub.docker.com/r/sandrokeil/TypeScript/
通常、いくつかの一般的なツールの汎用ラッパーとして設計されているため、複数のプロジェクトに同じdocker builderを使用することは問題ありません。しかし、より複雑な手順を説明する独自のビルドを作成してもかまいません。
ビルダーイメージの良い点は、ホスト環境が汚染されないままであり、ビルダーイメージのDockerfileを変更するだけで、新しいバージョンのコンパイラ/異なるツール/変更順序/タスクを並行して自由に試すことができることです。そして、いつでもビルド手順を使用して実験をロールバックできます。
個人的には、ビルド中にbabelを実行した後にdev依存関係を削除することを好みます。
FROM node:7
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Copy app source
COPY src /usr/src/app/src
# Compile app sources
RUN npm run compile
# Remove dev dependencies
RUN npm Prune --production
# Expose port and CMD
EXPOSE 8080
CMD [ "npm", "start" ]
この種の(Docker 17.05時点での)推奨事項は、 マルチステージビルド を使用することです。このようにして、1つのDockerfileですべてのdev/build依存関係を使用できますが、最終結果は最適化され、不要なコードがなくなります。
私はTypeScriptにそれほど詳しくありませんが、ここではyarnとbabelを使用した実装例を示します。このDockerfileを使用して、開発イメージを構築できます(docker build --target development .
)nodemon、テストなどをローカルで実行するため。しかし、ストレートdocker build .
pm2 でアプリを実行する、無駄のない最適化された製品イメージを取得します。
# common base image for development and production
FROM node:10.11.0-Alpine AS base
WORKDIR /app
# dev image contains everything needed for testing, development and building
FROM base AS development
COPY package.json yarn.lock ./
# first set aside prod dependencies so we can copy in to the prod image
RUN yarn install --pure-lockfile --production
RUN cp -R node_modules /tmp/node_modules
# install all dependencies and add source code
RUN yarn install --pure-lockfile
COPY . .
# builder runs unit tests and linter, then builds production code
FROM development as builder
RUN yarn lint
RUN yarn test:unit --colors
RUN yarn babel ./src --out-dir ./dist --copy-files
# release includes bare minimum required to run the app, copied from builder
FROM base AS release
COPY --from=builder /tmp/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
CMD ["yarn", "pm2-runtime", "dist/index.js"]
次の手順を実行します:
ステップ1:package.jsonのdevenciesではなくdependencies内にbabel依存関係があることを確認します。また、node_modulesフォルダーからbabelを参照しているデプロイスクリプトを追加します。 docker内からこのスクリプトを呼び出すことになります。これは、私のpackage.jsonファイルの外観です
{
"name": "tmeasy_api",
"version": "1.0.0",
"description": "Trade made easy Application",
"main": "build/index.js",
"scripts": {
"build": "babel -w src/ -d build/ -s inline",
"deploy" : "node_modules/babel-cli/bin/babel.js src/ -d build/",
},
"devDependencies": {
"nodemon": "^1.9.2"
},
"dependencies": {
"babel-cli": "^6.10.1",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-0": "^6.5.0",
"babel-preset-stage-3": "^6.22.0"
}
}
buildはローカルマシンでの開発目的のためで、deployはdockerfile内から呼び出されます。
ステップ2:自分でbabael変換を行いたいので、開発中に使用しているビルドフォルダーに.dockerignoreを追加してください。これが私の.dockerignoreファイルの外観です。
build
node_modules
ステップ3. dockerfileを作成します。以下は私のドッカーファイルのサンプルです
FROM node:6
MAINTAINER stackoverflow
ENV NODE_ENV=production
ENV PORT=3000
# use changes to package.json to force Docker not to use the cache
# when we change our application's nodejs dependencies:
ADD package.json /tmp/package.json
RUN cd /tmp && npm install
RUN mkdir -p /var/www && cp -a /tmp/node_modules /var/www
# copy current working directory into docker; but it first checks for
# .dockerignore so build will not be included.
COPY . /var/www/
WORKDIR /var/www/
# remove any previous builds and create a new build folder and then
# call our node script deploy
RUN rm -f build
RUN mkdir build
RUN chmod 777 /var/www/build
RUN npm run deploy
VOLUME /var/www/uploads
EXPOSE $PORT
ENTRYPOINT ["node","build/index.js"]
とりあえず、次のようなワークフローを使用しています。
npm install
およびtsd install
ローカルgulp
ローカルでビルドnpm install --production
このようにして、イメージ内の必要なファイルのみを取得しますが、Dockerfileがビルド自体を実行できればより良いでしょう。
Dockerfile:
FROM node:5.1
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Bundle app
COPY package.json index.js /usr/src/app/
COPY views/ /usr/src/app/views/
COPY build/ /usr/src/app/build/
COPY public/ /usr/src/app/public/
# Install app dependencies
RUN npm install --production --silent
EXPOSE 3000
CMD [ "node", "index.js" ]
「イメージングプロセス」の完全な自動化は、Dockerimageスクリプトを組み込み、不要なファイルを削除してから再インストールすることで確立できると思います。
ただし、私のプロジェクトでは、ソースを直接実行することはできません。ES6やTypeScriptからコンパイルする必要があります。私はgulpを使用してbabel、browserify、およびtsifyでビルドします。ブラウザーとサーバーのセットアップは異なります。 この場合、Dockerイメージを構築および自動化するための最適なワークフローは何ですか?
あなたが正しいことを理解したら、WebアプリをDockerコンテナ内にデプロイし、さまざまなターゲット環境にさまざまなフレーバーを提供する必要があります(さまざまなブラウザーとサーバーについて言及しました)。 (1)
Dockerfileがビルドを実行する必要がある場合-イメージにはすべてのdev依存関係が含まれている必要がありますが、これは理想的ではありませんか?
場合によります。すぐに使用できるイメージを提供する場合は、Webアプリを実行するために必要なすべてのものを含める必要があります。利点の1つは、後でコンテナを起動し、いくつかのパラメータを渡すだけで準備完了です。
開発段階では、通常事前に定義された開発環境のため、そのイメージは実際には必要ありません。変更のたびにそのようなイメージを生成する場合、時間とリソースがかかります。
推奨されるアプローチ:双方向のセットアップをお勧めします:
開発フェーズと展開フェーズの両方のDockerコンテナ:私と私の同僚のプロジェクトを参照したい: https:// github .com/k00ni/Docker-Nodejs-environment
このドッカーは、以下を維持することにより、開発およびデプロイ環境全体を提供します。
およびその他のJavaScriptヘルパー内Dockerコンテナー。 Dockerコンテナ内のボリュームを介してプロジェクトフォルダをリンクするだけです。環境を初期化します(たとえば、package.jsonからすべての依存関係をデプロイします)。
あなたはdevelopmentの目的に使用でき、あなたとあなたのチームは同じ環境(Node.jsバージョン、NPMバージョン、...)を使用します利点は、ファイルを変更すると、ECMA6/ReactJS/...ファイルがJavaScriptファイルに再コンパイルされることです(各変更後に手動でこれを行う必要はありません)。そのためにBabelを使用します。
deploymentの目的で、このDockerイメージを拡張し、必要な部分を変更するだけです。コンテナ内でアプリをリンクする代わりに、Git(またはそのようなもの)を介してプルできます。すべての作業に同じ地下室を使用します。