Docker Hub で公開されているイメージを元に、自作の Python プログラムを含めて Docker イメージを作成する工程をメモしておきます。
作成したイメージからコンテナを作成、コンテナ内で Python プログラムを実行するところまでカバーしています。
前提:Mac で Docker Desktop をインストール済み
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