Jex’s Note

Docker 基本教學

介紹

有點像 VM 但又不全然是 VM, 最主要它跟一般 VM 的差別在於 VM 所需的 OS 及 bins/libs 是安裝在 VM 本身裡面的

但 docker 的 container 概念會共用 OS 及 bins/libs, 但他們仍是獨立的, 由 Docker Engine 管理

最大好處可以快速啟動環境並且設定好, 很適合用在自動化測試或開發上

基本觀念

名詞解釋

  • image : 用來建立 container 的東西, 每一個 image 都只能讀且不能被改變
  • container : 是由一個 image 建立的一個的正在執行中的環境, 可以把它想成一台主機
  • 官方 registry : 就是 Docker Hub

Image

  • 一個完整 image 的名稱是 : username/image_name:tag
  • 一個 image 可以跑多個 container
  • 可以 commit 這個 container 的變動製作新的 image
  • image 想當於是 AWS EC2 的 AMI

Container

  • 把它想像 AWS EC2 的 Instances 清單 (相當於 docker ps -a)
  • 每一個主機都是一個 container,有些是 stopped 有些是 running (相當於 docker ps, 只列出 running container)
  • 只要被 Stop 的主機 (相當於 docker stop) 都是關機的狀態但還在列表上 (相當於還存在在 list 上 docker ps -a)
  • 被 Stop 的主機你可以再對它執行 Start (相當於 docker start)
  • 你可以對主機打成 image (相當於 docker commit)
  • 而被 Terminate 的主機就會被刪除,你無法在 Instances 上看到 (相當於 docker rm 後你無法在 docker ps -a 上再看到它)
  • 比較不一樣的是,執行中的 container 可以是直接進入(就像執行 ssh 到主機一樣)也可以是背景執行
  • 停止 container 不只是關機這麼簡單,連修改過的資料都會不見 (但可使用 mount 外部的檔案或資料夾來解決)

安裝

mac

可從官網下載

ubuntu

sudo apt-get install update && sudo apt-get install docker.io

執行 sudo adduser <username> docker, 將你加入到 docker group

windows

下載頁面

Exec : C:\Program Files\Boot2Docker for Windows\start.sh

putty / xshell connect to docker@127.0.0.1:2022

  • 預設的 VM VirtualBox 就已經設定好 port forwarding 了, 預設是 127.0.0.1:2022
  • Default account (docker / tcuser)

開始試玩

將 mysql 跑起來

Pull image mysql from docker hub

docker pull mysql

Run container mysql

docker run -t -d -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql

Test

mysql -h 127.0.0.1 -u root -p

將 redis 跑起來

Pull Docker Hub 上的 redis image

docker pull redis

將 redis image 啟動成 container, 並且將 6379 port 接出來

docker run -t -d -p 6379:6379 redis:latest

測試用 redis-cli 是否可以連進去

將 ubuntu image 跑起來 (建立一個 container)

Pull Docker Hub 上的 ubuntu image

docker pull ubuntu

以 ubuntu image 建立一個 container

docker run -t -d ubuntu

看看執行中的 container 有哪些,你可以看到剛剛建立的 container

docker ps

CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                               NAMES
bba4d449e053        ubuntu                       "/bin/bash"              52 seconds ago      Up 51 seconds                                           sharp_mestorf

Stop 後 docker ps 就看不到它了

docker stop bba4d449e053

但你顯示全部的 container 就看的到了

docker ps -a

你可以完全地刪除它

docker rm bba4d449e053

常用指令

build : 建立寫好的 Dockerfile

docker build -t jxxx/golang-env .

images : image list

docker images

rmi : 刪除 image

docker rmi eg_sshd

// 刪除全部 image
docker rmi $(docker images -q)

inspect : 查看此 container 的 info (不常用)

docker inspect f244dc51e1d9

ps : running container list (有哪些主機正在跑)

docker ps
  • -a : 所有 container ,即使是被 stop 的都會列出來
  • -q : 只顯示 CONTAINER ID

stop : 停掉在跑的 container (相當於關機)

docker stop {CONTAINER ID}

// 停掉全部在跑的 container
docker stop $(docker ps -a -q)

start : 將一個已經被 stop 的 container 再跑起來 (相當於開機)

docker start {CONTAINER ID}

rm : 刪除 container (相當於刪除這台主機)

docker rm {CONTAINER ID}

// 刪除全部 container
docker rm $(docker ps -a -q)

stop vs rm

  • stop : 將這個 container 關機並保存它的狀態, 只能在 docker ps -a 看到它, 你可以對它 commit 製作新的 image
  • stop : It sends SIGTERM first, then, after a grace period, SIGKILL.
  • rm : 將這個 container 真的刪除, 無法在 docker ps -a 看到它
  • rm : 你沒辦法 remove 一個 running container,必須先 stop 再 remove

start vs run

  • start : 將一個被 stop 的 container 重新啟動,就像開機一樣
  • run : 主機(container) 還沒建立,所以要將一個 image 建立一個 container

run

以 ubuntu image 建立 container 並進入到 container 裡面 (有點像 SSH 連進去,但 exit 後就是 stopped 的狀態了)

docker run -t -i ubuntu:14.04 /bin/bash
  • 如果沒有指定版本,預設會用最新的 ubuntu:latest
  • flag 可簡化為 -it
  • bash 也可以指定絕對路徑 /bin/bash

背景執行 container

docker run -t -d ubuntu:14.04

在 container 裡執行指令

docker run jxxx/golang-env touch ff.md

本機與 container 所有的 port

docker run -d -P jxxx/golang-env

-P flag to publish all of the exposed ports.

50080 port -> 80 port

docker run -d -p 50080:80 jxxx/golang-env

-p flag to publish a range of ports

將 domain 對應到 image name

docker run -d --link my_mysql:db.example.com jxxx/golang-env

將目錄名稱 folder_src mount 到 container 家目錄下(?)

docker run -v `pwd`/folder_src:/home/jex/into_container jxxx/golang-env ls -al into_container

Exec

進入正在執行中的container

docker exec -it <containerIdOrName> bash

Cp

將檔案複製到 container 裡

docker cp foo.txt {CONTAINER ID}:/foo.txt

將檔案從 container 裡複製出來

docker cp {CONTAINER ID}:/foo.txt ./

Commit

docker commit -m "Add ff.md" e3015 jxxx/golang-env

Push

docker push jxxx/golang-env

Attach

  • docker attach [CONTAINER ID] : 進入 container

Logs

將 container 的標準輸出接出來

docker logs {CONTAINER ID}

在 Docker config 設定將 log 接到標準輸出

RUN ln -sf /dev/stdout /var/log/test.log

其他指令

  • expose
  • add/copy
  • volume
  • attach/detach
  • pause/unpause
  • link between containers

Dockerfile 怎麼寫

FROM : 使用每個 image 為基礎

FROM ubuntu
FROM ubuntu:14.04

MAINTAINER : 設定產生的 imgage 的 Author

MAINTAINER Jex "xxxxxxx@gmail.com"

USER : 使用哪個 user 去執行 RUN, CMD etc.

USER daemon

RUN : 執行指令 (使用預設的 shell /bin/sh -c)

RUN apt-get update && apt-get -y upgrade

CMD : 執行 command

CMD echo "This is a test." | wc -       // 預設是使用 shell 執行  /bin/sh -c

CMD ["/usr/bin/wc","--help"]            // 執行其他指令不使用 shell 的話要使用 JSON format

ENV : 設定環境變數

ENV HOME /root

WORKDIR 設定工作目錄 (for any RUN, CMD, ENTRYPOINT, COPY and ADD in the Dockerfile)

WORKDIR /root
或
WORKDIR ${HOME}

ADD : 新增檔案

ADD xx.md /root
ADD xx.md $HOME

ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/         # adds "test" to /absoluteDir/

COPY : 複製檔案

COPY \$HOME /tmp

COPY test relativeDir/   # adds "test" to `WORKDIR`/relativeDir/
COPY test /absoluteDir/  # adds "test" to /absoluteDir/

EXPOSE : 開放哪些 Port

EXPOSE 80 443

HEALTHCHECK (https://docs.docker.com/engine/reference/builder/#/healthcheck)

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

SHELL : 更改預設的 shell (linux default : /bin/sh -c)

SHELL ["executable", "parameters"]

# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello

docker-compose

啟動

docker-compose up -d

指定 config

docker-compose -f custom.yml up -d

config

docker-compose.yml

version: "2"
services:

  test-redis:
    container_name: test-redis
    image: redis
    expose:
      - "6379"
    ports:
      - "6379:6379"
    volumes:
      - redis-data-test:/data-test

  test-mysql:
    container_name: test-mysql
    image: mysql/mysql-server:5.7
    expose:
      - "3306"
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    volumes:
      - dbdata-test:/var/lib/mysql

volumes:
  redis-data-test:
  dbdata-test:

Q&A

dial unix /var/run/docker.sock: permission denied

2014/12/23 14:14:33 Get http:///var/run/docker.sock/v1.12/images/json: dial unix /var/run/docker.sock: permission denied

sudo adduser <username> docker

Comments