---
title: docker
tags: docker
---
[toc]
# Docker vs VM

| 特性 | 說明 |
| -------- | -------- |
| 靈活性 | 複雜的應用程式也可以容器化 |
| 輕量化 | 容器共享內核,系統消耗比虛擬機器低 |
| 可移植 | 可在本地建構,部署到任何地方運行 |
| 低耦合 | 容器間相依低,更換或者升級不會影響其他容器 |
| 可擴展 | 可以在數據中心跑多個容器 |
| 安全性 | 容器之間預設的網路是隔離的 |
| 特性 | Docker | VM |
| -------- | -------- | --- |
| 啟動速度 | 秒級 | 分鐘級 |
| 硬碟使用 | 一般為MB | 一般為GB |
| 性能 | 接近原生 | 較差 |
| 系統支援量 | 單機支持上千容器 | 一般幾十個 |
| 隔離性 | 安全隔離 | 完全隔離 |
# 基本概念
* Image 映像檔
* Image是一個模板,用來產生容器
* Image包含完整的服務、編譯環境、或是作業系統
* Container 容器
* 容器是用映像檔建立出來的實體
* 它可以被啟動、開始、停止、刪除
* 每個容器都是相互隔離。
* Repository 倉庫
* 倉庫是映像檔存放的地方
* 倉庫可分為公開倉庫和私有倉庫
* Docker Hub是官方公開倉庫,存放了許多官方維護的映像檔供使用者下載
# install
```bash=
winget install -e --id Docker.DockerDesktop
brew install --cask docker
sudo apt-get install docker.io
```
# docker命令

```bash=
docker info
docker version
docker images
docker rmi $(docker images -f dangling=true -qa)
docker rmi $(docker images -qa)
# 以nginx為例
docker pull nginx:1.21.6-alpine
# 生命週期
watch docker ps -a
docker run -d --name w1 -p 8080:80 -v /tmp/html:/usr/share/nginx/html nginx:1.21.6-alpine
docker logs -f w1
docker stop w1
docker start w1
docker restart w1
docker pause w1
docker unpause w1
docker kill w1
docker rm w1
# 匯出匯入
watch docker images
docker run -i -t --rm --name w2 -p 8080:80 nginx:1.21.6-alpine
docker exec -i -t w2 sh
docker commit -m 'edit index' w2
docker cp w2:/usr/share/nginx/html/index.html .
docker cp ./index.html w2:/usr/share/nginx/html
docker export w2 > w2.tar
docker import ./w2.tar abc123:0.0.1
docker save abc123:0.0.1 > abc123.tar
docker rmi abc123:0.0.1
docker load < abc123.tar
docker stop w2
docker rmi nginx:1.21.6-alpine
docker tag abc123:0.0.1 nginx:1.21.6-alpine
```
# Dockerfile

```yaml=
# 基底映像檔
FROM ubuntu:20.04 as base
# 影像檔資訊
# LABEL maintainer="abc@example.com"
# LABEL description='abc123'
# 指定執行容器的user
USER node
# 容器編譯時期執行的命令
RUN apt-get update \
&& apt-get upgrade -y \
# 工作目錄
WORKDIR /app
# 容器執行時期的環境變數
ENV TYPEORM_HOST=127.0.0.1
ENV TYPEORM_USERNAME=usr
ENV TYPEORM_DATABASE=pwd
# 編譯時用 --build-arg 帶入的參數
# 容器編譯時期的變數
# ARG
# 複製本機的資料至容器內
COPY dist /app/dist
# 複製網路的資料,並自動解壓縮到容器內
# ADD https://www.example.com/abc.tar /app/lib/
# 建立一個可以對外掛載的目錄
# VOLUME
# 宣告此容器Listen的Port號
EXPOSE 3000
# 指定容器啟動程序及參數
# ENTRYPOINT ["entrypoint.sh"]
# 容器啟動時執行的命令
CMD ["node", "dist/main"]
```
```bash=
docker build -t abc:123 .
docker build -t abc:456 -f dev.dockerfile .
docker tag abc:123 xyz:456
```
```bash=
FROM busybox
ENTRYPOINT ["ping"]
CMD ["168.95.1.1"]
```
# Understand how CMD and ENTRYPOINT interact
[Understand how CMD and ENTRYPOINT interact](https://docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact)
## Node Js Dockerfile
```dockerfile=
FROM node:lts-alpine as base
RUN mkdir -p /app && chown -R node:node /app
USER node
WORKDIR /app
ENV NODE_ENV production
COPY --chown=node:node dist /app/dist
COPY --chown=node:node .npmrc package.json /app/
RUN npm install
EXPOSE 3000
CMD ["node", "dist/main"]
```
# docker compose
```yaml=
version: '3.5'
networks:
local:
name: local
services:
db:
container_name: 'mysql'
image: 'mysql:8.0.29'
command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: db01
MYSQL_USER: dev
MYSQL_PASSWORD: dev
ports:
- 3306:3306
networks:
- local
adminer:
container_name: 'adminer'
image: 'adminer:4.8.1'
restart: always
ports:
- 8080:8080
networks:
- local
```
```bash=
docker-compose up
docker-compose up -d
docker-compose down
docker-compose start
docker-compose stop
docker-compose restart
docker-compose build
docker-compose ps
docker-compose top
docker-compose images
docker-compose config
```
# Makefile
```
DIRNAME:= $(notdir $(CURDIR))
.PHONY: build
build:
docker build -t $(DIRNAME):local .
run:
docker run -i -t --rm -p 3000:3000 $(DIRNAME):local
rmi:
docker rmi $(DIRNAME):local
clean:
rm -rf coverage
rm -rf node_modules
rm -rf dist
rm -f junit.xml
rm -f package-lock.json
```
# Container Registry
[CNCF Container Registry](https://landscape.cncf.io/card-mode?category=container-registry&grouping=category)
* Harbor
* Portus
* Nexus Repository
* Docker Hub
* Google Container Registry
* Azuer Container Registry
* Amazon Elastic Container Registry