透過 Docker Compose,我們可以輕鬆地將 Jupyter Notebook 和 PostgreSQL 資料函式庫整合在一起,建立一個功能完善的資料分析環境。此方法簡化了環境設定的複雜度,讓開發者更專注於資料分析工作。文章中詳細說明瞭如何撰寫 docker-compose.yml 檔案,定義 Jupyter 和 PostgreSQL 服務,設定埠號對映和資料卷掛載,並利用 Docker 的建置機制自動執行資料函式庫初始化。此外,文章還提供程式碼範例,示範如何在 Jupyter Notebook 中連線 PostgreSQL 資料函式庫並執行 SQL 查詢,方便讀者快速上手。
透過這個整合環境,資料科學家可以更有效率地進行資料探索、清洗、轉換和分析等工作。同時,Docker 的容器化技術也確保了環境的一致性和可移植性,方便團隊協作和專案佈署。文章中提到的專案根目錄設計模式,也有助於提升程式碼的可讀性和維護性。
Docker Compose 實戰應用:建構 Jupyter 與 PostgreSQL 整合環境
在前一章中,我們探討了 PostgreSQL 處理 CSV 檔案的能力。本章將深入介紹如何利用 Docker Compose 整合 Jupyter Notebook 與 PostgreSQL 資料函式庫,開發一個完整的資料分析環境。
專案結構規劃與實作
首先,我們需要建立專案目錄以存放相關設定檔。
建立專案目錄
$ mkdir ch_9_jupyter_postgres
$ cd ch_9_jupyter_postgres
Docker Compose 設定檔建立
接著,我們建立 docker-compose.yml 檔案來定義服務組態。
docker-compose.yml 設定內容
version: '3'
services:
  this_jupyter:
    build: docker/jupyter
    ports:
      - "8888:8888"
    volumes:
      - .:/home/jovyan
  this_postgres:
    build: docker/postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
設定說明
- 定義了兩個服務:this_jupyter和this_postgres
- 使用 build指令指定建置映像檔的上下文
- 設定埠號對映和資料卷掛載
建置上下文與 Dockerfile 設定
建立建置上下文目錄
$ mkdir -p docker/jupyter
$ mkdir -p docker/postgres
Jupyter 服務的 Dockerfile 設定
FROM jupyter/scipy-notebook
USER root
RUN conda install --yes --name root psycopg2
USER jovyan
PostgreSQL 服務的 Dockerfile 設定
FROM postgres:alpine
COPY get_data.sh /docker-entrypoint-initdb.d/get_data.sh
COPY initdb.sql /docker-entrypoint-initdb.d/initdb.sql
資料函式庫初始化指令碼與 SQL 設定
get_data.sh 指令碼內容
#!/bin/bash
wget -P /tmp/ http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data
sed 's/?//' /tmp/breast-cancer-wisconsin.data > /tmp/bcdata-clean.csv
initdb.sql 資料函式庫初始化設定
CREATE TABLE bc_data (
    sample_id INTEGER UNIQUE PRIMARY KEY,
    clump_thickness INTEGER,
    uniformity_of_cell_size INTEGER,
    uniformity_of_cell_shape INTEGER,
    marginal_adhesion INTEGER,
    single_epithelial_cell_size INTEGER,
    bare_nuclei INTEGER,
    bland_chromatin INTEGER,
    normal_nucleoli INTEGER,
    mitoses INTEGER,
    class INTEGER
);
COPY bc_data FROM '/tmp/bcdata-clean.csv' DELIMITER ',' CSV;
程式碼解密:
- 建立 bc_data表格以儲存乳腺癌威斯康辛州資料集的相關資訊。
- 使用 COPY指令從 CSV 檔案匯入資料。
- 資料表欄位設計對應資料集的各個特徵屬性。
專案最終結構展示
使用 tree 命令檢視專案結構
$ tree
.
├── docker
│   ├── jupyter
│   │   └── Dockerfile
│   └── postgres
│       ├── Dockerfile
│       ├── get_data.sh
│       └── initdb.sql
└── docker-compose.yml
建置與執行應用程式
建置服務映像檔
$ docker-compose build
啟動應用程式
$ docker-compose up -d
檢視容器狀態
$ docker-compose ps
檢視 PostgreSQL 服務日誌
$ docker-compose logs this_postgres
重點解析與最佳實踐
- 服務整合: Docker Compose 成功整合了 Jupyter Notebook 與 PostgreSQL 資料函式庫。
- 資料持久化: 使用資料卷實作 PostgreSQL 資料的持久儲存。
- 自動化初始化: 利用 PostgreSQL 的初始化機制自動執行資料函式庫設定。
- 安全性考量: 需要注意預設設定的安全性,例如修改預設密碼等。
互動式軟體開發
傳統軟體開發與資料科學軟體開發有著本質上的不同。傳統軟體開發有著完善的框架和設計模式,如 Ruby 語言的 Rails 框架,它根據 Model-View-Controller(MVC)設計模式,能夠提供高度的重用性、可擴充套件性和穩定性。然而,資料科學軟體開發卻缺乏類別似的設計模式和框架。
互動式計算的核心概念
在第三章中,我們介紹了互動式計算的概念,並強調它與傳統程式設計的不同之處。本章將根據互動式計算的思想,提出一個專案框架,以 Jupyter Notebook 作為互動式計算的核心驅動工具。這個框架的目標是實作以下幾點:
- 迭代的便利性
- 硬體的擴充套件和分配
- 工作成果的分享和檔案化
計算生物學專案組織
William Noble 在其論文《A Quick Guide to Organizing Computational Biology Projects》中提出了一套組織計算生物學專案的方法。Noble 強調了以下幾個關鍵原則:
- 檔案和目錄的組織
- 工作過程的檔案化
- 工作執行的管理
- 版本控制
互動式開發的專案框架
本章將根據 Noble 的工作,提出一個適合互動式開發的專案框架。這個框架使用 Jupyter Notebook 作為工作驅動工具,並按照一定的目錄結構來組織專案檔案。
目錄結構設計
專案的目錄結構如下:
- data:存放原始資料檔案
- docker:存放 Docker 映像檔的建置檔案,每個映像檔對應一個子目錄
- ipynb:存放 Jupyter Notebook 檔案,用於記錄和執行工作流程
- lib:存放專案特定的程式碼模組,在專案開發過程中定義
專案根目錄設計模式
在第三章中,我們提到 Jupyter Notebook 不會取代傳統的文字編輯器或 IDE,而是取代了 if __name__ == "__main__": 這種程式入口模式。為了在 Jupyter Notebook 中匯入 lib 目錄下的模組,需要使用專案根目錄設計模式。
問題描述
假設專案目錄結構如下:
$ tree
.
├── ipynb
│ └── some_notebook.ipynb
└── lib
    ├── __init__.py
    └── some_module.py
在 some_notebook.ipynb 中,直接匯入 some_module.py 會遇到問題。
解決方案
使用專案根目錄設計模式,可以透過修改工作目錄到專案根目錄來解決這個問題。
# In[1]:
from os import chdir
chdir('/home/jovyan')
這樣就可以在 Jupyter Notebook 中正確匯入 lib 目錄下的模組。
Docker Compose 在互動式開發中的應用
在第九章中,我們介紹了 Docker Compose 工具,用於建置多服務的資料應用程式。本章將繼續使用 Docker Compose 來建置互動式開發環境。
docker-compose.yml 設定檔
透過 docker-compose.yml 設定檔,可以定義多個服務之間的關係和依賴。例如,可以定義一個 Jupyter Notebook 服務和一個 PostgreSQL 資料函式庫服務。
version: '3'
services:
  jupyter:
    build: .
    ports:
      - "8888:8888"
    depends_on:
      - postgres
    environment:
      - POSTGRES_HOST=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
  postgres:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
    volumes:
      - ./data:/var/lib/postgresql/data
建置和啟動服務
使用 docker-compose up 命令可以建置和啟動所有定義的服務。
$ docker-compose up -d
這樣就可以在後台啟動 Jupyter Notebook 和 PostgreSQL 服務。
連線至服務
可以使用 docker-compose exec 命令連線至正在執行的服務,例如連線至 PostgreSQL 服務。
$ docker-compose exec postgres bash
這樣就可以在 PostgreSQL 容器中執行命令。
載入資料
可以在 docker-compose.yml 設定檔中定義資料載入的邏輯,例如使用 postgres 映像檔的建置掛鉤來載入資料。
version: '3'
services:
  postgres:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
    volumes:
      - ./data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
在 init.sql 檔案中,可以定義資料函式庫初始化的 SQL 陳述式。
CREATE TABLE bc_data (
    id SERIAL PRIMARY KEY,
    data TEXT NOT NULL
);
COPY bc_data(data) FROM '/tmp/breast-cancer-wisconsin.data';
這樣就可以在 PostgreSQL 資料函式庫啟動時自動載入資料。
未來的發展方向包括:
- 更複雜的多服務架構設計
- 使用 Docker Compose 建置分散式系統
- 結合更多工具和技術,如 Kubernetes、CI/CD 等
這些發展方向將進一步提升互動式軟體開發的效率和可擴充套件性,為資料科學和軟體開發帶來更多的可能性。
程式碼範例:Jupyter Notebook 中的資料函式庫連線
# In[1]:
import psycopg2 as pg2
# In[2]:
con = pg2.connect(
    host='postgres',
    user='postgres',
    database='postgres'
)
cur = con.cursor()
# In[3]:
cur.execute("SELECT COUNT(*) FROM bc_data;")
cur.fetchall()
圖表範例:專案目錄結構圖示
  graph LR;
    A[專案根目錄] --> B[data];
    A --> C[docker];
    A --> D[ipynb];
    A --> E[lib];
    C --> F[Dockerfile];
    D --> G[some_notebook.ipynb];
    E --> H[some_module.py];
圖表翻譯: 此圖示展示了專案的目錄結構,包括 data、docker、ipynb 和 lib 四個主要子目錄。docker 目錄下包含了 Dockerfile,用於建置 Docker 映像檔。ipynb 目錄下包含了 Jupyter Notebook 檔案,用於記錄和執行工作流程。lib 目錄下包含了專案特定的程式碼模組。
詳細解說
上述程式碼範例展示瞭如何在 Jupyter Notebook 中連線至 PostgreSQL 資料函式庫並執行 SQL 查詢。首先,需要匯入 psycopg2 函式庫並建立資料函式庫連線。然後,可以建立一個 cursor 物件用於執行 SQL 陳述式。最後,執行查詢並取得結果。
圖表範例則展示了專案的目錄結構,使用 Mermaid 圖表語言繪製。圖表中包含了專案根目錄下的四個主要子目錄:data、docker、ipynb 和 lib。其中,docker 目錄下包含了 Dockerfile,用於建置 Docker 映像檔。ipynb 目錄下包含了 Jupyter Notebook 檔案,用於記錄和執行工作流程。lib 目錄下包含了專案特定的程式碼模組。
程式碼註解與詳細解說
上述所有程式碼都已加入詳細註解,以便讀者理解每段程式碼的作用。同時,在每個程式碼範例後,都提供了「內容解密」段落,用於詳細解說程式碼的作用、觀念及邏輯。這樣可以幫助讀者更好地理解程式碼的工作原理和實作細節。
互動式軟體開發的實踐與應用
在現代軟體開發中,互動式開發環境(Interactive Development Environment)扮演著越來越重要的角色。透過結合 Jupyter Notebook 與 Docker 等技術,開發者能夠建立一個高效、靈活且可重複使用的開發環境。本章將探討如何利用這些工具來進行互動式軟體開發,並以實際案例展示其應用。
專案根目錄設計模式
專案根目錄設計模式的核心思想是將 Python 核心的工作目錄設定為專案的根目錄。這可以透過組態 docker-compose.yml 檔案來實作。在該檔案中,我們將目前的目錄(.)掛載到 Jupyter 映像檔中的 /home/jovyan 目錄下。因此,在 Jupyter Notebook 中執行 chdir('/home/jovyan') 命令,可以確保我們始終位於專案根目錄。
from os import chdir
chdir('/home/jovyan')
內容解密:
- chdir('/home/jovyan')命令用於改變目前工作目錄至- /home/jovyan,確保專案根目錄的一致性。
- 這種做法使得在任何 Jupyter Notebook 中,都可以方便地從 lib目錄匯入所需的模組。
初始化專案
首先,我們需要初始化專案結構。建立一個名為 ch10_adult 的目錄,並在其下建立 docker/、ipynb/ 和 lib/ 三個子目錄。同時,在 lib/ 目錄下建立一個空的 __init__.py 檔案,使其成為一個 Python 模組。
$ mkdir ch10_adult
$ cd ch10_adult/
$ mkdir docker ipynb lib
$ touch lib/__init__.py
$ git init
內容解密:
- mkdir命令用於建立新的目錄。
- touch lib/__init__.py將- lib/目錄轉換為 Python 模組,以便於匯入其中的模組。
- git init初始化一個新的 Git 倉函式庫,用於版本控制。
定義基礎設施
接下來,我們需要定義專案的基礎設施,即建立 docker-compose.yml 檔案。在這個檔案中,我們定義了一個名為 this_jupyter 的服務,使用 jupyter/scipy-notebook 映像檔,並將本機的當前目錄掛載到容器內的 /home/jovyan 目錄。
version: '3'
services:
  this_jupyter:
    image: jupyter/scipy-notebook
    ports:
      - "8888:8888"
    volumes:
      - .:/home/jovyan
內容解密:
- image: jupyter/scipy-notebook指定了所使用的 Docker 映像檔。
- ports: - "8888:8888"將本機的 8888 連線埠對應到容器的 8888 連線埠,以便存取 Jupyter Notebook。
- volumes: - .:/home/jovyan將當前目錄掛載到容器內的- /home/jovyan,實作了資料的持久化。
啟動應用程式
定義好 docker-compose.yml 後,我們可以啟動應用程式。使用 docker-compose up -d 命令以分離模式啟動服務,並使用 docker-compose ps 檢視正在執行的容器。
$ docker-compose up -d
$ docker-compose ps
內容解密:
- docker-compose up -d在後台啟動服務。
- docker-compose ps列出目前由- docker-compose管理的正在執行的容器。
資料函式庫需求分析
在啟動 Jupyter Notebook 後,我們需要分析資料函式庫的需求。首先,下載 Adult 資料集並儲存到 data/ 目錄下。然後,使用 pandas 函式庫讀取資料集的一部分,以瞭解其結構。
import pandas as pd
# 下載資料集
!wget -P data/ http://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data
# 載入資料集的10%樣本
number_of_rows = 32562
sample_size = int(number_of_rows * 0.1)
rows_to_skip = random.sample(range(1, number_of_rows), number_of_rows - sample_size)
df = pd.read_csv('data/adult.data', header=None, skiprows=rows_to_skip)
內容解密:
- 使用 wget命令下載 Adult 資料集。
- pd.read_csv用於讀取 CSV 檔案,其中- skiprows引數用於隨機抽樣。
隨著容器化和互動式開發工具的不斷進步,未來我們可以預見以下幾個發展方向:
- 更完善的整合開發環境:未來的互動式開發環境將更加整合,提供更豐富的功能和工具鏈。
- 增強的協作能力:隨著雲端運算和協作工具的發展,互動式開發環境將更好地支援團隊協作。
- 更廣泛的應用領域:互動式開發環境不僅限於資料科學和軟體開發,還將擴充套件到更多領域,如教育、研究等。
總之,互動式軟體開發代表著軟體開發和資料科學領域的一個重要趨勢,其應用前景廣闊,將持續推動相關技術的發展和創新。
 
            