Day08 - Docker 101 Image 建置篇

前言

在前一天介绍了 Docker 容器操作的技巧,今天来透过 Lab 学习如何将专案建置成 Image ,并推送至 GCP 的 Container Registry。

重点整理

https://ithelp.ithome.com.tw/upload/images/20210908/20139235Xn7eSPFYmH.png

环境建置

若想要在自己的环境下安装 Docker,可以参考 Install Docker Engine 指南,本次 Lab 中,我们会使用在Day5 中介绍的 Cloud Shell,里面已经安装好 Docker 的环境,只要透过浏览器就能直接使用。

  1. 进入 Cloud Shell 网站

  2. 确认右上角编辑器与终端机皆已开启

  1. 点击终端机输入指令

  2. 检查docker版本,确认是否已安装

docker -v

(输出结果)

Docker version 20.10.8, build 3967b7d

准备 Web Service

还记得我们在 Day04 中使用 VM 来搭建出 Web Service。这次试着将服务用容器的方式来运行。而在制作容器所需的 Image 前,需要先确认程序能否正常执行,就来用 Cloud Shell 实际测试看看。

  1. 建立 project 资料夹
cd && mkdir project 
  1. 建立package.jsonapp.js档案
cd project && touch package.json app.js
  1. 点击左上 Explorer -> Open Folder -> 选择 project 资料夹 -> Open

  1. 点击app.js档案并贴上以下内容

https://ithelp.ithome.com.tw/upload/images/20210907/20139235BxAB127asD.png

  • app.js
const express = require('express')
const app = express()
const port = 8080

app.get('/', (req, res) => {
  res.send('Hello My Container Project!!')
})

app.listen(port, () => {
  console.log('Example app listening at port %s', port)
})

这次专案预设是监听 8080 Port

  1. 点击package.json档案并贴上以下内容

https://ithelp.ithome.com.tw/upload/images/20210907/20139235Swr7Y2tjI3.png

  • package.json
{
    "dependencies": {
        "express": "*"
    },
    "scripts": {
        "start": "node app.js"
    }
}

在 Cloud Shell 里面已经安装好了 NodeJS 以及 Npm,准备好程序码後安装完套件就能执行了。

  1. 安装所需套件
npm install
  1. 执行程序
npm start

(输出结果)

> start
> node app.js

Example app listening at port 8080
  1. 在cloud shell点击网页预览->透过以下通讯预览 : 8080

可以看到服务器回传讯息,代表 Web Service 建立成功。

https://ithelp.ithome.com.tw/upload/images/20210907/20139235NPmhN4uq8U.png

  1. 回到 Cloud Shell 终端机,点击Ctrl +c停止程序。

建立 Image

服务准备好了,那到底要怎麽建置 Image 呢?就是透过撰写Dockerfile,内容主要分为三个步骤。

  • 选择 Base Image
  • 执行安装指令和设置
  • 设定启动指令

首先会到 Docker Hub 找寻适合的Base Image,这里我们选择是 node。

https://ithelp.ithome.com.tw/upload/images/20210908/20139235JOrHQUaMy1.png

接着就可以建立 dockerfile 了。

  1. 建立dockerfiledockerignore档案
touch dockerfile .dockerignore
  1. 点击dockerfile档案并贴上以下内容

https://ithelp.ithome.com.tw/upload/images/20210907/20139235PP9H4WIcAd.png

  • dockerfile
# Select a base image
FROM node:alpine

# Run some commands and configurations
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080

# Set startup commands
CMD [ "npm", "start" ]
  • FROM node:alpine
    • 选择 Node 的轻量化版本作为 Base Image
  • WORKDIR /usr/src/app
    • 选择 /usr/src/app 做为工作资料夹
  • COPY package*.json ./
    • 将 package.json 复制到容器内部
  • RUN npm install
    • 在容器内部安装所需插件
  • COPY . .
    • 将程序码(如 app.js )复制到容器内部
  • EXPOSE 8080
    • 设定 Port 8080 为对外端口
  • CMD [ "npm", "start" ]
    • 启动指令设定为 npm start

为避免将不必要的档案也复制到容器里,所以会设定.dockerignore来忽略。

  1. 点击.dockerignore档案并贴上以下内容

https://ithelp.ithome.com.tw/upload/images/20210907/20139235kg93QimGH3.png

  • .dockerignore
.git
.env
*Dockerfile*
node_modules
npm-debug.log

写好了Dockerfile就可以使用docker build来建置 Image 了,为了区别每次 Build 的 Image ,所以会加上版本号。

  1. 回到 Cloud Shell 终端机,使用docker build
docker build -t node-project:v1 .

(输出结果)

Sending build context to Docker daemon   42.5kB
Step 1/7 : FROM node:alpine
alpine: Pulling from library/node
4e9f2cdf4387: Pull complete
631bfa39568f: Pull complete
9854121ede03: Pull complete
0d50f77f17a6: Pull complete
Digest: sha256:e250bb9fbb7b7dfa462aff25deffe986e448e0177838fee8b69103810f06932b
Status: Downloaded newer image for node:alpine
 ---> 195bb95229bd
Step 2/7 : WORKDIR /usr/src/app
 ---> Running in 38d3ec57d019
Removing intermediate container 38d3ec57d019
 ---> ac05354464d6
Step 3/7 : COPY package*.json ./
 ---> 3272711ed7ec
Step 4/7 : RUN npm install
 ---> Running in 0269829bf554

added 50 packages, and audited 51 packages in 2s

found 0 vulnerabilities
npm notice 
npm notice New minor version of npm available! 7.21.0 -> 7.22.0
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v7.22.0>
npm notice Run `npm install -g [email protected]` to update!
npm notice 
Removing intermediate container 0269829bf554
 ---> 13a4da6d5cea
Step 5/7 : COPY . .
 ---> 142abe6e3dab
Step 6/7 : EXPOSE 8080
 ---> Running in f9c1b1f5cf08
Removing intermediate container f9c1b1f5cf08
 ---> ade735d6413f
Step 7/7 : CMD [ "npm", "start" ]
 ---> Running in aee8f9a6fef8
Removing intermediate container aee8f9a6fef8
 ---> 313106b6e3c0
Successfully built 313106b6e3c0
Successfully tagged node-project:v1

docker build会根据你撰写的dockerfile使用 Base Image 来启动容器,再根据安装指令和设置执行在容器内部,最後就将容器输出成我们要的 Image。

  1. 使用docker images来查看
docker images

(输出结果)

REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
node-project   v1        313106b6e3c0   54 seconds ago   116MB
node           alpine    195bb95229bd   6 days ago       112MB
  1. 使用docker run建立专案容器
  • Image: node-project:v1
  • 将本机 8080 Port 转送到容器 80 Port : -p 8080:8080
  • 需要在背景执行: -d
docker run -p 8080:8080 -d node-project:v1
  1. 查看刚建置的容器
docker ps

(输出结果)

CONTAINER ID IMAGE           COMMAND                CREATED       STATUS       PORTS   
8c721a09b013 node-project:v1 "docker-entrypoint.s…" 2 seconds ago Up 2 seconds 0.0.0.0:8080->8080/tcp
  1. 在cloud shell点击网页预览->透过以下通讯预览 : 8080

可以看到服务器回传讯息,代表 Image 建置成功。

https://ithelp.ithome.com.tw/upload/images/20210907/20139235NPmhN4uq8U.png

将 Image 上传至 GCP Container Registry

最後我们把建置好的 Image 上传至 Container Registry 保存起来。

  1. 列出所有的 project ,找到之前在 GCP 专案的 PROJECT_ID
gcloud projects list

  1. 要将 Image Push 到 Registry ,需要把 Image tag 上 Registry 的位置,如下指令,并将<PROJECT_ID>改成 GCP 专案的 ID
docker tag node-project:v1 gcr.io/<PROJECT_ID>/node-project:v1
  1. 使用docker images来查看
docker images

(输出结果)

node-project                            v1     313106b6e3c 9 minutes ago 116MB
gcr.io/ninth-bonito-324214/node-project v1     313106b6e3c 9 minutes ago 116MB
node                                    alpine 195bb95229b 6 days ago    112MB
  1. 推送至 Container Registry,并将<PROJECT_ID>改成 GCP 专案的 ID
docker push gcr.io/<PROJECT_ID>/node-project:v1
  1. 进入 GCP 网站

  2. 点击搜寻栏->输入Container Registry->找到Container Registry

https://ithelp.ithome.com.tw/upload/images/20210907/20139235Tqc010Brzt.png

  1. 点击node-project

https://ithelp.ithome.com.tw/upload/images/20210907/201392350b4SUKvwT2.png

里面就会出现刚刚 Build 的 Image 了。

https://ithelp.ithome.com.tw/upload/images/20210907/20139235KOD8VDrwSm.png


<<:  【Day 8】Python JSON与demjson

>>:  Day 8 - Fun with HTML5 Canvas

计算机概论 - 资料处理 Data manipulation

由於大学跟研究所读的是电机工程,所以对於软件业来说我是个半路出家的人,所以在公司与同事交流或是合作的...

Python产生QRCode图片 - Python练习题一

Python练习题一 import qrcode import sys import os # 需要...

Day30 - 模型复杂度分析

在最後一天的内容中,我们会以参数量、乘法数、训练过程中每一个epoch所需的时间与测试过程中每一笔资...

Day29

草莓正在奋力地练习之前学过的 JavaScript,熊熊刚下班急忙忙地跑过来。 「草莓啊不好意思,公...

Day 8: 人工智慧在音乐领域的应用 (有趣的AI演算法二)

今天我们接续昨天的话题,继续来聊聊AI领域里面比较有趣的一些演算法。 蚂蚁演算法 (Ant Colo...