Docker入門
Dockerとは
Dockerは仮想環境を構築するためのツールで、OS上に「コンテナ」と呼ばれる仮想環境を構築できる。このコンテナ型の仮想環境では、ホストOSのカーネルを利用してあたかもゲストOSがあるように仮想環境を作り上げる。ゲストOSが不要になるため、一般的な仮想環境と比較して軽量で高速に仮想環境を利用できる。
Dockerをインストールする
VSCodeでDockerを使う
【準備】拡張機能のインストール
【基礎編】簡単なサンプルコンテナを動かす
以下のようなファイル構成で設定ファイル群を作成していく
venv_docker_sample1
├ .devcontainer
| ├ python
| | ├ Dockerfile
| | └ requirements.txt
| ├ compose.yml
| └ devcontainer.json
└ python
└ src
└ sample.py
※ 各ファイルの簡単な説明
# .devcontainer/python/Dockerfile
FROM python:3.11-slim
WORKDIR /tmp/work
COPY requirements.txt ${PWD}
RUN pip install -r requirements.txt
# .devcontainer/python/requirements.txt
numpy == 1.24.3
matplotlib == 3.7.1
# .devcontainer/compose.yml
services:
python:
image: ex21/python:1.0
build: ./python
container_name: 'ex21-python'
stdin_open: true
tty: true
working_dir: '/tmp/waaork'
volumes:
- ../python:/tmp/work
// .devcontainer/devcontainer.json
{
"name": "Python Basic Project",
"dockerComposeFile": "compose.yml",
"service": "python",
"workspaceFolder": "/tmp/work",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python"
],
"settings": {
"editor.tabSize": 4
}
}
}
}
# python/sample.py
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 100, 0.5)
Hz = 5.
y = np.sin(2.0 * np.pi * (x * Hz) / 100)
plt.plot(x, y)
plt.savefig('test.png')
$ python sample.py
【発展編】Django×PostgreSQLコンテナを動かす
以下のようなファイル構成で設定ファイル群を作成していく
venv_docker_sample2
├ .devcontainer
| ├ web
| | ├ Dockerfile
| | └ requirements.txt
| ├ .env
| ├ compose.yml
| └ devcontainer.json
├ db
| └ init
| ├ 01_create_tables.sql
| ├ 02_insert_data.sql
| └ 03_settings.sql
├ web
└ .gitignore
※ 各ファイルの簡単な説明
# .devcontainer/web/Dockerfile
# M1Macの場合は以下を指定
# FROM python:3.11
# それ以外の場合は以下を指定
FROM python:3.11-slim
# パッケージのインストール
RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends \
tzdata sudo\
&& rm -rf /var/lib/apt/lists/*
# モジュールのインストール
WORKDIR /tmp/work
COPY requirements.txt ${PWD}
RUN pip install -U pip \
&& pip install -r requirements.txt
# 環境変数の定義
ENV TZ="Asia/Tokyo"
# 一時変数の定義
ARG USERNAME=user1
ARG PASSWORD=user1
ARG GROUPNAME=user1
ARG UID=1000
ARG GID=1000
# 一般権限のユーザーを追加
RUN groupadd -g ${GID} ${GROUPNAME} \
&& useradd -u ${UID} -g ${GID} -G sudo -m -s /bin/bash ${USERNAME} \
&& echo ${USERNAME}:${PASSWORD} | chpasswd \
&& echo "%${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# ユーザーの切替
USER ${USERNAME}
# .devcontainer/web/requirements.txt
django == 4.2.2
# M1Macの場合は以下を指定
# psycopg2
# それ以外の場合は以下を指定
psycopg2-binary == 2.9.6
# .devcontainer/.env
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
# .devcontainer/compose.yml
services:
db:
image: postgres:alpine3.18
container_name: "django-db"
expose:
- "5432"
environment:
- TZ=Asia/Tokyo
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- ../db/database:/var/lib/postgresql/data
- ../db/init:/docker-entrypoint-initdb.d
web:
image: django/web:1.0
build: ./web
container_name: "django-web"
ports:
- 8001:8000
environment:
- DEBUG=1
depends_on:
- db
stdin_open: true
tty: true
volumes:
- ../web:/home/user1/dev
// .devcontainer/devcontainer.json
{
"name": "Django Web",
"dockerComposeFile": "compose.yml",
"service": "web",
"workspaceFolder": "/home/user1/dev",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python"
],
"settings": {
"editor.tabSize": 4
}
}
}
}
/* db/init/01_create_tables.sql */
create table book
(
id serial NOT NULL PRIMARY KEY,
title text,
insert_timestamp timestamp with time zone
);
/* db/init/02_insert_data.sql */
INSERT INTO book VALUES(DEFAULT, 'プログラミング言語C', current_timestamp);
INSERT INTO book VALUES(DEFAULT, 'やさしいコンピューター科学', current_timestamp);
INSERT INTO book VALUES(DEFAULT, 'ゲーデル、エッシャー、バッハ―あるいは不思議の環', current_timestamp);
INSERT INTO book VALUES(DEFAULT, 'TeXブック コンピュータによる組版システム', current_timestamp);
INSERT INTO book VALUES(DEFAULT, '人月の神話 狼人間を撃つ銀の弾はない', current_timestamp);
/* db/init/03_settings.sql */
set timezone to 'Asia/Tokyo';
# .gitignore
/db/database
/web/log
$ django-admin startproject myprj .
$ django-admin startapp myapp
# myprj/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', # アプリを追加
]
# myprj/settings.py
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
DATABASES = {
'default': {
# M1Macの場合は以下を指定
# 'ENGINE': 'django.db.backends.postgresql',
# それ以外の場合は以下を指定
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'django-db',
'PORT': '5432',
}
}
# myapp/models.py
class Book(models.Model):
title = models.TextField(blank=True, null=True)
insert_timestamp = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'book'
# myapp/admin.py
from .models import Book
admin.site.register(Book)
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser
# Username:admin
# Email address:admin@example.com
# Password:<任意のパスワード>
# Password(again):<任意のパスワード>
# Superuser created successfully.
$ python manage.py runserver 0.0.0.0:8000
コンテナとイメージの削除
エラーが出る場合
設定ファイルが正しく記述されているにも関わらず、コンテナ立ち上げ時にエラーが出る場合がある。その際、コンテナの名前や使用しているportが重複していることが原因である場合が多く、以前作成したコンテナやイメージを削除するとうまくいくことがある。