プレスリリースやお知らせ、開発ブログ、会社の活動状況、Mattermost・aws・AI等の技術情報などを発信しています。

docker init してみる

こんにちは sakasai です。

皆さんコンテナしてますか?

今回はDockerの機能 docker init を試してみました。

docker initとは

開発中のソフトウェアプロジェクトに、Dockerで実行するために必要なソフトウェアをまとめて導入するコマンドです。

https://docs.docker.com/engine/reference/commandline/init/

※2023-5-29時点ではベータ版として提供されています。

2023-5-2に公開された「Docker Desktop 4.19」で docker init がPythonとNode.jsにも対応するようになりました。

前バージョンのv4.18でまずはGo言語に対応する形で提供されていましたが、対応言語が増えた形になります。

今後もJava,Rustなど対応言語が増える予定のようです。

やってみる

v4.18で docker init コマンドが提供された時点では完全にスルーしてしまっていたのですが、

\Pythonに対応した/

ということで試してみました。

環境は以下です。

  • PC
MacBook Pro Apple M1
macOS Ventura 13.3.1
  • docker
$ docker version
Client:
 Cloud integration: v1.0.31
 Version:           23.0.5
 API version:       1.42
 Go version:        go1.19.8
 OS/Arch:           darwin/arm64
 Context:           desktop-linux

Server: Docker Desktop 4.19.0 (106363)
 Engine:
  Version:          23.0.5
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.8
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.20
 runc:
  Version:          1.1.5
 docker-init:
  Version:          0.19.0

※一部省略しています。


それではやってみます。

今回は FastAPI を使ったアプリケーションをdocker環境で作っていこうと思います。

まず任意のディレクトリで docker init コマンドを実行します。

以下対話形式で選択・入力していきます。

最初に使用する言語を聞かれるのでPythonを選択します。

$ docker init

Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with sensible defaults for your project:
  - .dockerignore
  - Dockerfile
  - compose.yaml

Let's get started!

? What application platform does your project use?  [Use arrows to move, type to filter]
  Go - suitable for a Go server application
> Python - suitable for a Python server application
  Node - suitable for a Node server application
  Other - general purpose starting point for containerizing your application
  Don't see something you need? Let us know!
  Quit

次に使用するバージョンを聞かれるので今回は実行時点のデフォルトの3.11.3を使います

? What version of Python do you want to use? 3.11.3

次にアプリケーションで使用するポート番号が聞かれます。

こちらもデフォルトのまま8000を使用します。

? What port do you want your app to listen on? 8000

最後にアプリケーションの実行コマンドを聞かれます。

今回はFastAPIのアプリケーション起動で使用する以下を入力します。

? What is the command to run your app (e.g., gunicorn 'myapp.example:app' --bind=0.0.0.0:8000)? uvicorn main:app --host 0.0.0.0 --port 8000 --reload

この状態で以下の3ファイルが作成され

CREATED: .dockerignore
CREATED: Dockerfile
CREATED: compose.yaml

最後にコンソールに以下が出力され、docker環境の準備ができた状態になります。

✔ Your Docker files are ready!

Take a moment to review them and tailor them to your application.

WARNING: No requirements.txt file found. Be sure to create one that contains the dependencies for your application, including an entry for the uvicorn package, before running your application.

When you're ready, start your application by running: docker compose up --build

Your application will be available at http://localhost:8000

requirements.txt がないという警告が出ていますが一旦次に進みます。


それでは作成されたファイルを見てみましょう。

$ cat .dockerignore
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

**/.DS_Store
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

docker実行時に無視するファイルが定義されています。 ADDやCOPYから除外してくれるようです(使ったことありませんでした。。)

$ cat Dockerfile 
# syntax=docker/dockerfile:1

# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/engine/reference/builder/

ARG PYTHON_VERSION=3.11.3
FROM python:${PYTHON_VERSION}-slim as base

# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1

# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1

WORKDIR /app

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser

# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
# Leverage a bind mount to requirements.txt to avoid having to copy them into
# into this layer.
RUN --mount=type=cache,target=/root/.cache/pip \
    --mount=type=bind,source=requirements.txt,target=requirements.txt \
    python -m pip install -r requirements.txt

# Switch to the non-privileged user to run the application.
USER appuser

# Copy the source code into the container.
COPY . .

# Expose the port that the application listens on.
EXPOSE 8000

# Run the application.
CMD uvicorn main:app --host 0.0.0.0 --port 8000 --reload

docker init で設定したPythonのバージョンやアプリケーションのポート、起動コマンドが設定されていることがわかります。

$ cat compose.yaml 
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Docker compose reference guide at
# https://docs.docker.com/compose/compose-file/

# Here the instructions define your application as a service called "server".
# This service is built from the Dockerfile in the current directory.
# You can add other services your application may depend on here, such as a
# database or a cache. For examples, see the Awesome Compose repository:
# https://github.com/docker/awesome-compose
services:
  server:
    build:
      context: .
    ports:
      - 8000:8000

# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker compose up`.
#     depends_on:
#       db:
#         condition: service_healthy
#   db:
#     image: postgres
#     restart: always
#     user: postgres
#     secrets:
#       - db-password
#     volumes:
#       - db-data:/var/lib/postgresql/data
#     environment:
#       - POSTGRES_DB=example
#       - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
#     expose:
#       - 5432
#     healthcheck:
#       test: [ "CMD", "pg_isready" ]
#       interval: 10s
#       timeout: 5s
#       retries: 5
# volumes:
#   db-data:
# secrets:
#   db-password:
#     file: db/password.txt

アプリケーション用のコンテナー定義のみ有効になっている状態でDBのサンプル等はコメントアウトされた状態になっています。(コメントアウトした状態でサンプルを用意してくれてるのは親切でいいですね)


作成されたファイルの内容を確認できたので早速dockerコンテナを起動したいところですが、その前に警告が出ていた requirements.txt を作成します。

今回使用するFastAPIのみライブラリのみ定義しておきます。

$ echo "fastapi[all]" > requirements.txt
$ cat requirements.txt 
fastapi[all]

ここまでできた状態でコンテナを起動してみます。

$ docker compose up --build
...
Attaching to your-container-name
your-container-name  | INFO:     Will watch for changes in these directories: ['/app']
your-container-name  | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
your-container-name  | INFO:     Started reloader process [7] using WatchFiles
your-container-name  | ERROR:    Error loading ASGI app. Could not import module "main".

ビルドが成功しコンテナが起動しますが、まだ何もアプリケーションに実装を行っていないためエラーになっています。

チュートリアル を参考に main.py ファイルを作ります。

$ cat main.py 
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}

一度コンテナを停止(CTRL+C)した後に再度実行します。

$ docker compose up --build
...
Attaching to your-container-name
your-container-name  | INFO:     Will watch for changes in these directories: ['/app']
your-container-name  | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
your-container-name  | INFO:     Started reloader process [7] using WatchFiles
your-container-name  | INFO:     Started server process [9]
your-container-name  | INFO:     Waiting for application startup.
your-container-name  | INFO:     Application startup complete.

起動が成功していることを確認してブラウザで http://localhost:8000 にアクセスすると {"message":"Hello World"} が表示されることが確認できます。

以上で docker init で作ったdocker環境でアプリケーションの作成、実行ができることが確認できました。

さいごに

docker init を使って環境の作成とアプリケーションの実行を行ってみました。

今までもdockerを使っていた人は今回やったような内容では自分で作ったほうが早かったりするかもしれませんが、

これからdockerを始める人や、たまに使うためその都度Dockerfileやdocker-composeファイルの書き方を調べながらやっている人にとっては嬉しい機能なのではないかと思います。

docker init で作られたファイルを参考にそれぞれのファイルの書き方を学ぶのにもいいかもしれません。

というわけで、これからもdockerを便利に使っていきましょう。

...締めの言葉がいまいちなのでChatGPTに考えてもらいました。

以上が、Dockerの新機能「docker init」についての解説です。初期設定ファイルの生成を自動化し、コンテナ化への道のりを容易にするこの新機能は、Dockerユーザーにとって有用なツールとなることでしょう。しかし、現在はまだベータ版であるため、本番環境での使用は慎重に行ってください。最新の情報については公式ドキュメントを参照し、Dockerの進化を引き続き見守りましょう。

ChatGPT(GPT-4)
  • B!

おすすめ記事リンク