Docker Hub で公開されているイメージを元に、自作の Python プログラムを含めて Docker イメージを作成する工程をメモしておきます。
作成したイメージからコンテナを作成、コンテナ内で Python プログラムを実行するところまでカバーしています。
前提:Mac で Docker Desktop をインストール済み
- Python 関連の準備
- Python プログラムの準備
- requirements.txt の作成
- Docker 関連の準備
- Dockerfile の作成
- .dockerignore の作成
- docker build でイメージを作成
- コンテナの作成と Python プログラムの実行
- docker run でイメージを実行
- コンテナに入ってみる
- Python プログラムを実行してみる
- コンテナ脱出、コンテナ停止、コンテナ削除
1. Python 関連の準備
1. Python プログラムの準備
まずは下準備として Python 仮想環境をローカル環境に作り、コンテナ内で実行したい Python プログラムを用意します。
とりあえず手持ちのプログラム「amazon_scraping.py」を使いまわします。仮想環境と横並びで配置しています。
% ls
amazon_scraping.py venv
Amazon の商品リストページの情報をスクレイピングして CSV ファイルにアウトプットするプログラムです。
# amazon_scraping.py
from datetime import date
from time import sleep
import csv
import requests
from bs4 import BeautifulSoup
domain_name = 'amazon.co.jp'
search_term = 'iPhone 12'
url = f'https://www.{domain_name}/s?k={search_term}'.replace(' ','+')
urls = []
for i in range(1,2):
urls.append(f'{url}&page={i}')
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15',
'Host':f'www.{domain_name}'
}
# Request each URL, convert into bs4.BeautifulSoup
soups = []
for url in urls:
response = requests.get(url,headers=headers)
soup = BeautifulSoup(response.content, 'html.parser')
soups.append(soup)
sleep(0.5)
# Convert delivery date
def format_delivery_date(date_string):
if len(date_string) == 0:
return None
if date_string[-2:] == '曜日':
date_string = date_string[:-3]
if date_string[0:3] == '明日中' and date_string[-4:] == '1月/1':
date_string = date_string.replace('明日中','2024/')
elif date_string[0:3] == '明日中':
date_string = date_string.replace('明日中','2023/')
date_string = date_string.replace('月/','/')
return date_string
# Extract data from bs4.BeautifulSoup
def scan_page(soup, page_num):
products = []
for product in soup.select('.s-result-item'):
asin = product['data-asin']
a_spacing_top_small = product.select_one('.a-spacing-top-small')
a_section_list = product.select('.sg-row .a-section')
for a_section in a_section_list:
price_elem = a_section.select_one('.a-price .a-offscreen')
if price_elem:
price = int(price_elem.get_text().replace('¥', '').replace(',',''))
continue
delivery_date_by = a_section.select_one('span:-soup-contains("までにお届け")')
if delivery_date_by:
delivery_date = format_delivery_date(a_section.select('span')[1].text)
continue
if asin:
products.append({'asin': asin, 'price': price, 'delivery_date': delivery_date, 'page_number': page_num})
return products
for page_num, soup in enumerate(soups):
dict_list = scan_page(soup, page_num+1)
fieldnames = dict_list[0].keys()
with open('output.csv', 'w', newline='') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(dict_list)
print('csv file created')
標準ではないモジュールとして、requests と beautifulsoup4 を pip でインストールします。
(venv) % pip install requests
(venv) % pip install beautifulsoup4
2. requirements.txt の作成
次に requirements.txt を作ります。
% pip freeze > requirements.txt
(venv) % ls
amazon_scraping.py requirements.txt venv
中身は下記の様になっています。
# requirements.txt
beautifulsoup4==4.12.2
certifi==2023.5.7
charset-normalizer==3.1.0
idna==3.4
requests==2.30.0
soupsieve==2.4.1
urllib3==2.0.2
3. .dockerignore の作成
「venv」配下は必要ないため、イメージに含めない様「.dockerignore」に追加します。
# .dockerignore
venv
とりあえず Python プログラムの下準備はここまでです。
2. Docker 関連の準備
1. Dockerfile を作る
仮想環境のディレクトリと横並びで Dockerfile というファイルを作成します。
ubuntu:20.04 のイメージを元に、Python および使用するモジュールをインストールする様記述します。
# Dockerfile
FROM ubuntu:20.04
#apt の最新化の後 python と pip をインストール
RUN apt update
RUN apt install -y python3.9
RUN apt install -y python3-pip
# 作業ディレクトリを /var に移動
WORKDIR /var
# ローカル環境の amazon_scraping.py をコンテナへコピー
COPY amazon_scraping.py .
# ローカル環境の requirements.txt をコンテナへコピーし、中身を pip install
COPY requirements.txt .
RUN python3.9 -m pip install -r requirements.txt
中身は上記の通りで、ubuntu:20.04 のイメージを元に、ファイルのコピーやインストールをおこないます。
「ls」を実行すると下記の状態です。
(venv) % ls
Dockerfile amazon_scraping.py requirements.txt venv
2. docker build でイメージを作成
「docker build」コマンドを実行します。
% docker build -t docker_amzn:1.0 .
[+] Building 239.4s (13/13) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 253B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.9s
=> [1/8] FROM docker.io/library/ubuntu:20.04@sha256:db8bf6f4fb351aa7a26e27ba2686cf35a6a409f65603e59d4c203e58387dc6b3 4.2s
=> => resolve docker.io/library/ubuntu:20.04@sha256:db8bf6f4fb351aa7a26e27ba2686cf35a6a409f65603e59d4c203e58387dc6b3 0.0s
=> => sha256:db8bf6f4fb351aa7a26e27ba2686cf35a6a409f65603e59d4c203e58387dc6b3 1.13kB / 1.13kB 0.0s
=> => sha256:b795f8e0caaaacad9859a9a38fe1c78154f8301fdaf0872eaf1520d66d9c0b98 424B / 424B 0.0s
=> => sha256:88bd6891718934e63638d9ca0ecee018e69b638270fe04990a310e5c78ab4a92 2.30kB / 2.30kB 0.0s
=> => sha256:ca1778b6935686ad781c27472c4668fc61ec3aeb85494f72deb1921892b9d39e 27.50MB / 27.50MB 2.9s
=> => extracting sha256:ca1778b6935686ad781c27472c4668fc61ec3aeb85494f72deb1921892b9d39e 0.9s
=> [internal] load build context 0.0s
=> => transferring context: 2.67kB 0.0s
=> [2/8] RUN apt update 62.4s
=> [3/8] RUN apt install -y python3.9 35.9s
=> [4/8] RUN apt install -y python3-pip 130.6s
=> [5/8] COPY requirements.txt . 0.0s
=> [6/8] RUN python3.9 -m pip install -r requirements.txt 2.7s
=> [7/8] WORKDIR /var 0.0s
=> [8/8] COPY /venv/amazon_scraping.py . 0.0s
=> exporting to image 2.6s
=> => exporting layers 2.6s
=> => writing image sha256:9f3dfca1f57b234294ed4666ea9d6dc05f7200cf30c6c10bbebf83834ae6e457 0.0s
=> => naming to docker.io/library/docker_amzn:1.0 0.0s
%
数分かかりましたが無事完了。「docker images」コマンドで作成済みのイメージを確認できます。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker_amzn 1.0 9f3dfca1f57b 59 seconds ago 473MB
3. コンテナに入ってみる
1. docker run でイメージを実行
「docker run」コマンドで Docker イメージからコンテナを作成します。
コンテナ外からのアクセスはしないのでポートフォワーディング(-p オプション)は指定していません。
% docker run --name amzn_scraper -it -d docker_amzn:1.0
47caefa69121c3323c7379f448952003001817e937ffb3232d4564fce9b3c01c
2. コンテナに入ってみる
% docker exec -it amzn_scraper bash
root@47caefa69121:/var#
「ls」を実行すると、Dockerfile で COPY の記述をした amazon_scraping.py や requirements.txt がコンテナに存在することを確認できます。
root@cd3f7f913010:/var# ls
amazon_scraping.py backups cache lib local lock log mail opt requirements.txt run spool tmp
3. Python プログラムを実行してみる
そのままコンテナ内で Python プログラムを実行してみます。
root@cd3f7f913010:/var# python3.9 amazon_scraping.py
csv file created
ファイルが作成された様です。
root@cd3f7f913010:/var# ls
amazon_scraping.py backups cache lib local lock log mail opt output.csv requirements.txt run spool tmp
「head」コマンドで中身も確認。きちんと作成されている様です。
root@cd3f7f913010:/var# head output.csv
asin,price,delivery_date,page_number
B0BDHLR5WP,164800,,1
B0BDHYRRQX,134800,,1
B09M69W9KR,234801,,1
B09M68Y2HZ,162800,,1
B0928MGLCR,50025,,1
B0928LZ4HD,67980,2023/5/19,1
B08B9WMNSS,49490,,1
B0928L4D5H,92430,,1
B08B9GTC1T,78695,,1
8. コンテナ脱出、コンテナ停止、コンテナ削除
コンテナ脱出
# exit
exit
コンテナ停止
% docker stop amzn_scraper
amzn_scraper
% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
47caefa69121 docker_amzn:1.0 "/bin/bash" 13 minutes ago Exited (0) 2 seconds ago amzn_scraper
コンテナ削除
% docker rm amzn_scraper
amzn_scraper
% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES