主頁 >  其他 > Docker-核心筆記(含Dockerfile,Compose)

Docker-核心筆記(含Dockerfile,Compose)

2020-09-16 22:20:25 其他

Docker-核心筆記(含Dockerfile,Compose)

2017/03 Chenxin

參考
https://yeasy.gitbooks.io/docker_practice Docker入門與實踐 電子書,截止201807一直在更新.
http://guide.daocloud.io/dcs/daocloud-services-9152632.html Docker加速器
https://blog.csdn.net/S_gy_Zetrov/article/details/78161154 入門
http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html
http://www.ruanyifeng.com/blog/2018/02/docker-wordpress-tutorial.html

命令自動補全(不屬于docker內容)
安裝(僅支持較新的linux版本)

yum install bash-completion

說明(可以忽略)
最小化安裝centos7需要安裝一個 bash-completion 包,然后退出 bash,重新登錄即可.
bash-2.05及以后的版本提供了自動補齊的編程介面.
bash-completion的安裝已加入Centos7初始化腳本.

常用指令匯總

yum install docker # 安裝

docker version
docker info
docker search centos
docker pull centos:latest 
 
docker image ls --all
docker image rmi image_id     # 洗掉
docker image save image_id -o centosvim.tar    # 輸出一個tar格式的
docker image load -i centosvim.tar    # 載入一個tar格式的
docker image tag image_id centosvim:1.0
docker image inspect image_id    #獲取鏡像元資料

docker container ls --all 
docker container attach container_id    # ctrl+p, ctrl+q 將容器推到后臺后,推薦使用exec方式進入,防止退出的時候錯誤的將容器終止了(Ctrl+d)
docker container exec -it container_id /bin/bash    # 推薦
docker container exec -it --user root container_id /bin/bash      #登陸容器,并成為root
docker container run -it --name container_name image_id /bin/bash     #啟動一個容器
docker container run -d -p 1022:80 foo/live /bin/bash    #物理機的1022映射到docker的80;
docker container run -d -p 127.0.0.2:8080:80 --rm --name wordpress --env WORDPRESS_DB_PASSWORD=123456 --link wordpressdb:mysql --volume "$PWD/wordpress":/var/www/html wordpress
docker container run   -p 1022:80 -it centos:lastest /bin/bash    
docker container port     container_id
docker container inspect     container_id    #獲取容器元資料
docker container cp container_id:[/path/to/file] /local/path/dir/
docker container commit -m "centos with vim" -a "chenxin" container_id chenxin/centos:vim
docker container rm container_id
docker container prune     #洗掉所有處于stop狀態的container
docker container stats container_id     #顯示當前運行的這個容器資源占用情況(CPU/MEM/NET/IO/PIDS)
docker container top container_id     #顯示容器中當前運行的pid資訊
docker container start container_id
docker container stop container_id
ctrl+p ctrl+q     # 容器正常運行,用戶臨時退出bash
exit  / ctrl+d   # 用戶退出,可能導致容器stop

docker diff container_id    # 查看容器存盤層改動記錄
docker history image_id    # 查看image內的歷史記錄(每層改動情況)

docker build -t xbzj .    # 使用Dockerfile構建鏡像

用戶權限

普通用戶執行docker指令需要的權限
xbzj賬號執行 docker search java
報錯Got permission denied while trying to connect to the Docker daemon socket at ...permission denied
將xbzj加入到docker用戶組就可以了: usermod -G docker xbzj

安裝部署/目錄說明/啟停方式

網路說明
因大陸訪問海外download.docker.com存在網路問題.可以使用rpm方式安裝.之后可以使用大陸第三方提供的Docker庫(比如阿里云,或daocloud)
AWS上本身有docker庫,可以直接yum安裝.如果增加yum源安裝官網版本,需要解決一些依賴問題.
建議采取yum方式安裝(AWS默認的yum源)
docker分為社區版(ce)和企業版(ee收費)
官方安裝檔案 https://docs.docker.com/install/linux/docker-ce/centos/#uninstall-old-versions

yum安裝方式
a.配置yum倉庫(aws不需此步驟)
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
ls /etc/yum.repos.d/
amzn-main.repo docker-ce.repo

b.正式安裝
yum install docker-ce
這里會報依賴錯誤.可以自行解決.或使用AWS自身的yum源(推薦)
yum install docker (aws只需要這一步就可以了)

rpm安裝方式
https://download.docker.com/linux/centos/7/x86_64/stable/Packages/
https://download.docker.com/
rpm安裝完成后,執行rpm -ql docker
/etc/rc.d/init.d/docker #啟動關停狀態查看腳本
/etc/sysconfig/docker #組態檔,可以配置docker的一些目錄資訊和日志資訊
/etc/sysconfig/docker-storage #檔案配置
/etc/udev/rules.d/80-docker.rules
/usr/bin/docker
/usr/bin/docker-containerd
/usr/bin/docker-containerd-shim
/usr/bin/docker-ctr
/usr/bin/docker-init
/usr/bin/docker-proxy
/usr/bin/docker-runc
/usr/bin/dockerd
/usr/share/bash-completion/docker
/usr/share/vim/vimfiles/syntax/dockerfile.vim
/var/lib/docker #主要目錄

安裝完成后的驗證
執行docker version
Client:
Version: 18.03.1-ce #這個是aws自己的版本,是18年03月做的AMI.

docker主要目錄說明
ls /var/lib/docker/
builder containerd containers image network overlay2 plugins runtimes swarm tmp trust volumes

/var/lib/docker/devicemapper/devicemapper/data #用來存盤相關的存盤池資料
/var/lib/docker/devicemapper/devicemapper/metadata #用來存盤相關的元資料,
/var/lib/docker/devicemapper/metadata/ #用來存盤 device_id、大小、以及傳輸_id、初始化資訊
/var/lib/docker/devicemapper/mnt #用來存盤掛載資訊

/var/lib/docker/container/ #用來存盤容器資訊
/var/lib/docker/graph/ #用來存盤鏡像中間件及本身詳細資訊和大小 、以及依賴資訊
/var/lib/docker/repositores-devicemapper #用來存盤鏡像基本資訊
/var/lib/docker/tmp #docker臨時目錄
/var/lib/docker/trust #docker信任目錄
/var/lib/docker/volumes #docker卷目錄

docker啟停
service docker start 或者 systemctl start docker

鏡像與源站說明

查詢鏡像
docker search centos

拉取
docker pull centos
或者
docker pull centos:latest

會默認放到/var/lib/docker/overlay2/目錄,進入查看如下:
ls /var/lib/docker/overlay2/00...28/diff
bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
目錄和檔案內容跟我們安裝系統后的相同(連日志都有了).

鏡像源地址
a.查看鏡像源地址
docker info

b.修改鏡像源地址(2種方式)

1.增加或修改/etc/docker/daemon.json (18.03版本后就沒有這個檔案了aws的centos18.03版本.只能新增.1.13版本有這個檔案centos7yum安裝)

{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}

2.修改或新增 /etc/sysconfig/docker,在OPTIONS變數后追加引數

OPTIONS="--default-ulimit nofile=1024:4096 --registry-mirror=https://docker.mirrors.ustc.edu.cn"

修改完成后,重啟docker.經過測驗,以上2個地址都可用.

Docker國內源

a.國內源
Docker 官方中國區 https://registry.docker-cn.com
中國科技大學 https://docker.mirrors.ustc.edu.cn
網易 http://hub-mirror.c.163.com
阿里云 https://pee6w651.mirror.aliyuncs.com
默認docker源: Registry: https://index.docker.io/v1/

b.加速器
需要注冊的加速器使用說明:
登陸阿里云docker的registry:(需要先注冊阿里云賬號,在容器鏡像服務里配置registry密碼.將生成的鏡像url復制到docker組態檔里,類似:https://2r6ncmdxli.mirror.aliyuncs.com 的地址.
docker login --username=chenxin6676 registry.cn-shanghai.aliyuncs.com
之后在本地可以push鏡像到阿里云.

查看docker鏡像版本
查看docker鏡像的版本號TAG,從遠程倉庫拉取自己想要版本的鏡像.需要在docker hub查看
地址如下:https://hub.docker.com/r/library/
進入之后,在頁面左上角搜索框搜索.
點擊 詳情->TAG.
docker pull java:latest

docker指令使用說明

1 查看本地鏡像

docker image ls --all

2 容器啟動引數

docker container run -it --name test image_id /bin/bash 

具有自動抓取 image 的功能.如果發現本地沒有指定的 image 檔案,就會從倉庫自動抓取.
-t 選項讓Docker分配一個偽終端(pseudo-tty)并系結到容器的標準輸入上
-i 則讓容器的標準輸入保持打開
--name test:容器的名字叫做test.

docker container run --rm --name wordpress --volume "$PWD/":/var/www/html php:5.6-apache

--rm:停止運行后,自動洗掉容器檔案.
--volume "$PWD/":/var/www/html:將宿主機當前目錄($PWD變數內容)映射到容器的/var/www/html.
php:5.6-apache : 來源鏡像

docker container run -d --rm --name wordpressdb --env MYSQL_ROOT_PASSWORD=123456 --env MYSQL_DATABASE=wordpress mysql:5.7

-d:容器啟動后,在后臺運行.
--env MYSQL_ROOT_PASSWORD=123456:向容器行程傳入一個環境變數MYSQL_ROOT_PASSWORD,該變數會被用作 MySQL 的根密碼.
--env MYSQL_DATABASE=wordpress:向容器行程傳入一個環境變數MYSQL_DATABASE,容器里面的MySQL會根據該變數創建一個資料庫wordpress
mysql:5.7 : 來源鏡像

docker container run -d -p 127.0.0.2:8080:80 --rm --name wordpress --env WORDPRESS_DB_PASSWORD=123456 --link wordpressdb:mysql --volume "$PWD/wordpress":/var/www/html wordpress

-p 127.0.0.2:8080:80:物理機127.0.0.2的8080映射到器的 80 埠.
--link wordpressdb:mysql,表示 wordpress 容器要連到(先前創建的)wordpressdb容器,冒號表示該容器的別名是mysql.
瀏覽器訪問物理機127.0.0.2:8080就能看到 WordPress 的安裝提示了.而且,你在wordpress子目錄下的每次修改,都會反映到容器里面.
最后,終止上面這兩個容器(--rm,容器檔案會自動洗掉): docker container stop wordpress wordpressdb

docker container run -d -p 10.0.0.10:8080:80 --volume /home/admin/www/:/usr/local/apache2/htdocs --name apache httpd    或者
docker container run -d -p 8080:80 --volume ...xxx...

以上使用一個httpd的鏡像創建一個apache的容器
docker啟動容器的時候,可以指定容器的IP地址,但需要額外配置網路模式,具體請參考網上資料https://blog.csdn.net/sbxwy/article/details/78962809 .

3 detach容器
如果想讓容器一直運行,而不是停止,可以使用快捷鍵 ctrl+p ctrl+q 退出,此時容器的狀態為Up.

4 attach進入到這個容器
exec方式進入(run的時候沒有指定 -it /bin/bash的)容器

docker container exec -it [containerID] /bin/bash

如果docker run命令運行容器的時候,沒有使用-it引數,就要用這個命令進入容器.一旦進入了容器,就可以在容器的 Shell 執行命令了.

docker container attach container_id    # 不推薦此方式.推薦exec方式,因為attach完,直接ctrl+d,容器狀態會變成exited.而exec不會.

5 終止容器(多種方式)
在容器內,使用 exit,命令退出,則容器的狀態處于Exit,而不是后臺運行.
或者 docker container stop [containID]
或者 docker container kill [containID]

6 查看當前運行的容器/已停止的容器

docker container ls 同 docker ps (查看正在run中的容器)
docker container ls --all 同 docker ps -a 查看所有容器,包括停止的(Exited狀態)
docker container rm `docker container ls -aq` 只列出docker container的id,并洗掉掉所有container.

7 啟動、停止、重啟容器

docker container start ca5b2982c795 #[containID]
docker container stop ca5b2982c795
docker container restart ca5b2982c795
docker stop $(docker ps -aq) 停止所有的容器    

8 與宿主機間對拷檔案

docker container cp [containID]:[/path/to/file] /local/path/dir/    # 拷貝容器內檔案到物理機上

9 commit指令
commit利用container創建image.
應用場合,比如被入侵后保存現場等,但是,不要使用 docker commit 定制鏡像,定制鏡像應該使用 Dockerfile 來完成,

docker container commit -m "centos with vim" -a "chenxin" container_id chenxin/centos:vim

-m指定說明資訊;
-a指定用戶資訊;
ca5b2982c795代表容器的id;
chenxin/centos:vim指定目標鏡像的用戶名、倉庫名和 tag 資訊.
查看我們剛剛創建鏡像對應生成的檔案
/var/lib/docker/image/overlay2/imagedb/metadata/sha256/38...348/ 這里是lastUpdated和parent的2個文本檔案說明(起源于哪個鏡像).
/var/lib/docker/image/overlay2/imagedb/content/sha256/38...348 這個文本檔案詳細說明了這個鏡像的配置資訊

10 洗掉 容器/鏡像

洗掉單個容器    docker container rm [containerID] (非運行狀態的才允許洗掉,否則請先docker stop/kill)
洗掉全部容器    docker container rm `docker container ls -aq`  或 docker container rm `docker ps -aq`   
洗掉單個鏡像    docker image rmi image_id
洗掉所有鏡像    docker image rmi `docker image ls -aq`    
洗掉所有在 mongo:3.2 之前的鏡像:docker image rmi $(docker image ls -q -f before=mongo:3.2) # -f為filter.
洗掉一個運行中的容器,可以添加 -f 引數    docker container rm -f myweb
洗掉所有處于終止狀態的容器        docker container prune

docker rm : 洗掉一個或多個 容器
docker rmi :  洗掉一個或多個 鏡像
docker prune: 用來洗掉不再使用的 docker 物件 

11 將image匯出后再匯入其他裝了docker的機器

docker image save image_id -o centosvim.tar #如何將自己的image硬拷貝
docker image load -i centosvim.tar #將tar檔案拷貝到其他機器后,執行匯入image
docker image tag 38f309423638 centosvim:1.0 #上面的REPOSITORY/TAG都是none,那么可以tag

12 push自己的image到第三方倉庫(aws)

a.將自己的image給push到docker官方的hub
這里需要到官方注冊賬號才行.需要先登錄 docker login;然后 docker push chenxin/centos:vim .這樣以后可以通過自己的賬號可以從官網pull下來自己的image.

b.將image給push到aws的ECR(ERS)

docker build -t xbzj .    # 首先本地構建鏡像,以xbzj為例
aws ecr get-login --no-include-email --region ap-southeast-1 #執行awscli指令獲取登陸ECR命令
docker login -u AWS -p eyJwY...M30= https://61..9551.dkr.ecr.a..t-1.amazonaws.com  #根據上條命令輸出登陸token,登陸完成.
docker tag xbzj:latest 61..51.dkr.ecr.ap-southeast-1.amazonaws.com/xbzj:latest   #對image打TAG
docker push 615..51.dkr.ecr.ap-southeast-1.amazonaws.com/xbzj:latest  #將本地image給PUSH到ECR

13 埠映射NAT
docker啟動服務,開啟埠,如何映像到外部的IP和埠,從而對外提供服務(2種方式).
容器中啟動的服務,可以通過宿主機直接訪問(route物理機會看到172.17.0.0的路由docker0),但外部機器無法訪問,那么就需要將docker埠映射到宿主機埠上.
查看物理機路由表,執行

# route
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.17.0.0      *               255.255.0.0     U     0      0        0 docker0

2種方式,如下:
1.通過容器指令(推薦)

docker container run -d -p 1022:80 foo/live /bin/bash    #物理機的1022映射到docker的80;
docker container run -p 1022:80 -it centos:lastest /bin/bash    #將物理機的1022埠映射docker的80埠
docker container run -d -p 10.0.0.10:1022:80 --volume /home/admin/www/:/usr/local/apache2/htdocs --name apache httpd    # 指定了映射到哪個物理網卡
docker container run -d -P  image_id #這里的大寫P,會將物理機隨機1個埠映射到Dockfile檔案EXPOSE宣告的埠上.

2.通過iptables的映射

docker inspect container_id |grep IPAddress    ->172.17.0.2
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.2:8000     # 將物理機的8001映射到容器的8000.
進入docker container里,啟動httpd服務,并netstat檢查:/usr/sbin/httpd
檢查物理機埠開放:    
tcp        0      0 :::8000     :::*    LISTEN      14066/docker-proxy  

14 容器的 volume 子命令 (或 -v)
docker專門提供了volume子命令來操作資料卷:
create 創建資料卷
inspect 顯示資料卷的詳細資訊
ls 列出所有的資料卷
prune 洗掉所有未使用的 volumes,并且有 -f 選項
rm 洗掉一個或多個未使用的 volumes,并且有 -f 選項

15 關于容器和鏡像的掛載卷說明
一.通過docker run命令.在docker run后的 -v 指令(只對創建的容器有效)

1、運行命令:docker run --name test -it -v /home/xqh/myimage:/data ubuntu /bin/bash    -> 主機上的 /home/xqh/myimage 目錄中的內容關聯到 容器中設定了一個掛載點 /data.在容器還是主機上操作它,都是完全實時同步的(實際指向的物理空間完全相同).
2、運行命令:docker run --name test1 -it -v /data ubuntu /bin/bash    ->docker會自動系結主機上的一個目錄到容器的/data上,(其目的不是讓在主機上修改,而是讓多個容器共享,)

二.通過dockerfile創建鏡像宣告的掛載點.
通過dockerfile的 VOLUME 方式對鏡像有效.(在鏡像中創建掛載點).與容器-v引數相比,有一個區別是,通過 VOLUME 指令創建的掛載點,無法指定主機上對應的目錄,是自動生成的,

FROM ubuntu
MAINTAINER hello1
VOLUME ["/data1","/data2"]

上面的dockfile檔案通過VOLUME指令指定了兩個掛載點 /data1 和 /data2. 如果用此鏡像創建容器,則容器中的/data1和/data2是隨機掛載的物理主機上的目錄.

三.容器共享卷(掛載點) --volumes-from (會將原容器的dockerfile中宣告的資料卷共享到自己這個容器上來,以便保持這個目錄與原容器的一致)

docker run --name test1 -it myimage /bin/bash    #myimage是用前面的dockerfile檔案構建的鏡像, 這樣容器test1就有了 /data1 和 /data2兩個掛載點,
下面我們創建其他容器可以和test1共享 /data1 和 /data2卷 ,在 docker run中使用 --volumes-from標記,如:
來源不同鏡像,如:docker run --name test2 -it --volumes-from test1  ubuntu  /bin/bash
來源相同鏡像,如:docker run --name test3 -it --volumes-from test1  myimage  /bin/bash
上面的三個容器 test1 , test2 , test3 均有 /data1 和 /data2 兩個目錄,且目錄中內容是共享的,任何一個容器修改了內容,別的容器都能獲取到,

四.最佳實踐:資料容器
如果多個容器需要共享資料(如持久化資料庫、組態檔或者資料檔案等),可以考慮創建一個特定的資料容器,該容器有1個或多個卷,其它容器通過--volumes-from 來共享這個資料容器的卷,
因為容器的卷本質上對應主機上的目錄,所以這個資料容器也不需要啟動,如: docker run --name dbdata myimage echo "data container"
說明:有個卷,容器之間的資料共享比較方便,但也有很多問題需要解決,如權限控制、資料的備份、卷的洗掉等,這些內容以后介紹,

16 對比 mount 掛載資料卷 方式 的說明

之前我們使用 --volume(-v) 選項來掛載資料卷,現在 docker 提供了更強大的 --mount 選項來管理資料卷,mount 選項可以通過逗號分隔的多個鍵值對一次提供多個配置項,因此 mount 選項可以提供比 volume 選項更詳細的配置,使用 mount 選項的常用配置如下:
type 指定掛載方式,我們這里用到的是 volume,其實還可以有 bind 和 tmpfs,
volume-driver 指定掛載資料卷的驅動程式,默認值是 local,
source 指定掛載源,對于一個命名的資料卷,這里應該指定這個資料卷的名稱.在使用時可以寫source,也可以簡寫為 src
destination 指定掛載的資料在容器中的路徑,在使用時可以寫 destination,也可以簡寫為 dst 或 target,
readonly 指定掛載的資料為只讀,
volume-opt 可以指定多次,用來提供更多的 mount 相關的配置,
下面我們看個具體的例子:
$ docker volume create hello
$ docker run -id --mount type=volume,source=hello,target=/world ubuntu /bin/bash
我們創建了名稱為 hello 的資料卷,然后把它掛在到容器中的 /world 目錄,通過 inspect 命令查看容器的詳情中的 "Mounts" 資訊可以驗證.

使用 volume driver 把資料存盤到其它地方
除了默認的把資料卷中的資料存盤在宿主機,docker 還允許我們通過指定 volume driver 的方式把資料卷中的資料存盤在其它的地方,比如 AWS 的 S3,
簡單起見,我們接下來的 demo 演示如何通過 vieux/sshfs 驅動把資料卷的存盤在其它的主機上,
docker 默認是不安裝 vieux/sshfs 插件的,我們可以通過下面的命令進行安裝:
$ docker plugin install --grant-all-permissions vieux/sshfs
然后通過 vieux/sshfs 驅動創建資料卷,并指定遠程主機的登錄用戶名、密碼和資料存放目錄:

docker volume create --driver vieux/sshfs \
    -o [email protected]:/home/nick/sshvolume \
    -o password=yourpassword \
    mysshvolume

注意,請確保你指定的遠程主機上的掛載點目錄是存在的(demo 中是 /home/nick/sshvolume 目錄),否則在啟動容器時會報錯,
最后在啟動容器時指定掛載這個資料卷:

docker run -id \
    --name testcon \
    --mount type=volume,volume-driver=vieux/sshfs,source=mysshvolume,target=/world \
    ubuntu /bin/bash

這就搞定了,你在容器中 /world 目錄下操作的檔案都存盤在遠程主機的 /home/nick/sshvolume 目錄中,進入容器 testcon 然后在 /world 目錄中創建一個檔案,然后打開遠程主機的 /home/nick/sshvolume 目錄進行查看,你新建的檔案是不是已經出現在那里了!

17 物理機與運行中的容器 資料的覆寫問題
以物理機器下的卷優先,以有資料的優先.

  • 如果掛載一個空的資料卷到容器中的一個非空目錄中,那么這個目錄下的檔案會被復制到資料卷中,
  • 如果掛載一個非空的資料卷到容器中的一個目錄中,如果容器目錄中原先有資料,那么容器中原始資料會被隱藏掉.
    這兩個規則都非常重要,靈活利用第一個規則可以幫助我們初始化資料卷(物理設備)中的內容,掌握第二個規則可以保證掛載資料卷后的資料總是你期望的結果,
    在 Dockerfile 中添加資料卷(鏡像里的資料卷宣告)(請參考本筆記 "Dockerfile撰寫" )

18 查看輸出和日志(重要,常用)
docker container logs [container-id/names] # 獲取容器的輸出資訊(類似控制臺輸出等)
docker container logs service-match|tail -n 100

19 控制容器占用系統資源(CPU,記憶體)
docker create 或者 docker run 的時候
-c|–cpu-shares[=0]引數來調整同期使用CPU的權重.
-m|–memory引數來調整容器使用記憶體的大小.

如何創建docker的私有倉庫 即 Docker Registry 搭建

1.從官方pull一個registery的鏡像,通過該鏡像與物理機本地檔案做好 --volume
2.修改物理機的鏡像源站地址
可以參考
https://cloud.tencent.com/developer/article/1015137
https://juejin.im/post/5a4ac6806fb9a045104ad7c8

其他概念
倉庫(Repository) 是存放一組關聯鏡像的集合,比如同一個應用的不同版本的鏡像,
注冊服務器(Registry) 是存放實際的鏡像的地方,
注冊索引(Index) 則負責維護用戶的賬號,權限,搜索,標簽等管理,

注冊服務器利用注冊索引來實作認證等管理,

如何啟動容器后,服務行程自啟動

構建鏡像

FROM centos-base:latestMAINTAINER [email protected]
ENTRYPOINT ["/config/bootstrap.sh"]
CMD ["/bin/bash"]

此處指定了ENTRYPOINT、CMD命令.CMD命令為bash,我們構建的鏡像一定是有bash行程的,有問題可以直接進行排查.

準備bootstrap.sh
在容器內部,撰寫腳本,腳本內容直接復制

mkdir /config
mkdir /config/init
vi /config/bootstrap.sh
chmod 755 /config/bootstrap.sh

問題
在你的Dockerfile中
RUN service mysql restart && /tmp/setup.sh
首先,docker鏡像不快照您的運行行程,您的RUN命令只是在docker構建階段運行,您需要指定命令運行時容器開始使用CMD或ENTRYPOINT命令,如 CMD mysql start
其次Docker容器需要行程(最后一個命令)保持運行,否則容器將退出.因此正常的服務mysql啟動命令不能直接在Dockerfile中使用

解決方案:為了保持行程正常運行:
通常方式Dockerfile
使用service命令,并附加非end命令后,像tail -F,如下:
CMD service mysql start && tail -F /var/log/mysql/error.log
或使用前臺命令來執行此操作,如下:
CMD /usr/bin/mysqld_safe

能否將腳本放到/etc/rc.local 來實作呢?經過測驗,貌似不行,原因應該是執行完后,自動退出了當前shell行程.

docker啟動流程/關閉流程/狀態說明

啟動流程
docker run -it ubuntu /bin/bash 首先系統要有一個docker daemon的后臺行程在運行,當剛才這行命令敲下時:

  • 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
  • 利用鏡像創建并啟動一個容器.
  • 分配一個檔案系統,并在只讀的鏡像層外面掛載一層可讀寫層
  • 從宿主主機配置的網橋介面中橋接一個虛擬介面到容器中去
  • 從地址池配置一個 ip 地址給容器
  • 執行用戶指定的應用程式
  • 執行完畢后容器被終止
    最后,我們就得到了一個ubuntu的虛擬機,然后就可以進行各種操作了.

關閉流程
docker stop (默認會10秒超時后再kill)或直接docker kill(直接kill -9) .stop的話,會保持現場到磁盤,優雅的關閉.

容器狀態說明
Up 正在運行 Exited 已經停止 Created 已創建未運行

關于持久化

持久化涉及到的外掛資料卷(有狀態,緊耦合類的應用)
默認不掛載外部存盤,則資料會和容器同生共死(違背了計算和資料分離原則),為容器的遷移或者故障恢復制造了麻煩,
所以一般采用-v引數掛外部卷.rm掉舊容器再重新run一個,把-v的卷掛回去就恢復了,
另外-v可以掛多個物理磁盤或者外部存盤,也解決了io瓶頸的問題,

一般設定Volume的場景:
組態檔目錄,資料檔案目錄,重要的日至檔案目錄.

容器中安裝軟體

  • 安裝軟體

需要先apt-get update,這個命令的作用是:同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,這樣才能獲取到最新的軟體包.否則安裝的時候會提示:E: Unable to locate package xxx(如vim)

vim 安裝 apt-get install vim
net-tools工具包 (含netstat route ifconfig mii-tool arp 等) apt-get install net-tools
procps工具包 (含 ps free ) apt-get install procps
rcconf (類似ntsyv,圖形界面配置服務) apt-get install rcconf
update-rc.d (debian默認已安裝,功能類似chkconfig)
iputils-ping (ping功能)

Dockerfile 撰寫

201807 Chenxin
參考
docker從入門到實踐(一直更新): https://yeasy.gitbooks.io/docker_practice/image/build.html
Dockerfile實踐: https://www.cnblogs.com/jsonhc/p/7767669.html
xbzj的Dockerfile檔案,請參見"k8s筆記內容".

Dockerfile 定制鏡像原理說明

dockerfile概念說明
在空目錄中,創建Dockerfile檔案.Dockerfile指令.大小寫不敏感(推薦大寫)

  • 示例-Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • 構建-Dockerfile
    docker build -t nginx:v3 . # 這里的"."就是context(鏡像構建背景關系) -t指明創建的鏡像名稱

鏡像構建背景關系(Context)
docker build 命令最后有一個"."表示當前目錄,這里是指明了背景關系路徑(context的路徑),而非指明Dockerfile檔案所在路徑.

  • docker build 的作業原理

Docker 在運行時分為 Docker 引擎(服務端守護行程)和客戶端工具,Docker 的引擎提供了一組 REST API,被稱為 Docker Remote API,而如 docker 命令這樣的客戶端工具,則是通過這組 API 與 Docker 引擎互動,從而完成各種功能,因此,雖然表面上我們好像是在本機執行各種 docker 功能,但實際上,一切都是使用的遠程呼叫形式在服務端(Docker 引擎)完成,也因為這種 C/S 設計,讓我們操作遠程服務器的 Docker 引擎變得簡單.
當我們進行鏡像構建的時候,并非所有定制都會通過 RUN 指令完成,經常會需要將一些本地檔案復制進鏡像,比如通過 COPY 指令、ADD 指令等,而 docker build 命令構建鏡像,其實并非在本地構建,而是在服務端,也就是 Docker 引擎中構建的,那么在這種C/S的架構中,如何才能讓服務端獲得本地檔案呢?

這就引入了背景關系的概念,當構建的時候,用戶會指定構建鏡像背景關系的路徑,docker build 命令得知這個路徑后,會將路徑下的所有內容打包,然后上傳給 Docker 引擎,這樣 Docker 引擎收到這個背景關系包后,展開就會獲得構建鏡像所需的一切檔案,

如果在 Dockerfile 中這么寫: COPY ./package.json /app/
這是復制 背景關系(context) 目錄下的 package.json,因此,COPY 這類指令中的源檔案的路徑都是相對路徑,如果真的需要那些并不在context目錄下的檔案,應該將它們復制到context目錄中去,

如果觀察 docker build 輸出,我們其實已經看到了這個發送背景關系的程序:

$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB ...

一般,應該將 Dockerfile 置于一個空目錄下,或者專案根目錄下,如果該目錄下沒有所需檔案,那么應該把所需檔案復制一份過來,如果目錄下有些檔案不希望構建時傳給 Docker 引擎,那么可以用".dockerignore"(剔除檔案串列,不傳遞給 Docker 引擎).

那么為什么會有人誤以為"."是指定 Dockerfile 所在目錄呢?在默認情況下,如果不額外指定 Dockerfile 的話,會將背景關系目錄下的名為 Dockerfile 的檔案作為 Dockerfile,實際上 Dockerfile 的檔案名并不要求必須為 Dockerfile,且并不要求必須位于背景關系目錄中,比如可以用

-f ../docker-file.txt 

引數指定某個檔案作為 Dockerfile,

當然,一般大家習慣性的會使用默認的檔案名 Dockerfile,以及會將其置于鏡像構建背景關系目錄中,

Dockerfile指令說明

FROM
指定基礎鏡像

LABEL
可選的

RUN
執行命令.制作image程序中執行的事項.每執行1次RUN,就會構建1個臨時image.
其格式有兩種:

* shell 格式:RUN <命令>,就像直接在命令列中輸入的命令一樣.RUN <cmd> 這個會當作/bin/sh -c “cmd” 運行,
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html 

* exec 格式:RUN ["可執行檔案", "引數1", "引數2"],這更像是函式呼叫中的格式,
RUN ["executable",  "arg1", .. ],Docker把他當作json的順序來決議,因此必須使用雙引號,而且executable需要完整路徑.

Dockerfile 中每一個指令都會建立一層.很多初學者制作出很臃腫的鏡像原因之一,就是忘記了每一層構建的最后沒有清理掉無關檔案.

CMD
執行指令或傳遞引數
執行container時候的默認啟動命令.可能會被覆寫(比如,當運行container的時候宣告了command,則不再用image中的CMD定義的命令)
一個Dockerfile中定義多個CMD的時候,只有最后一個才會起作用.

CMD定義的三種方式:
CMD <cmd> 這個會當作/bin/sh -c "cmd"來執行    # shell方式
CMD ["executable","arg1",....]    # 推薦exec方式
CMD ["arg1","arg2"],這個時候CMD作為ENTRYPOINT的引數

對容器而言,啟動程式就是啟動容器應用行程. 容器就是為了主行程而存在的,主行程退出,容器就失去了存在的意義,從而退出,不會關心輔助行程.
而使用 service nginx start 命令,則是希望用 upstart 方式以后臺守護行程形式啟動 nginx 服務,而剛才說了 CMD service nginx start 會被理解為 CMD [ "sh", "-c", "service nginx start"],因此主行程實際上是 sh,那么當 service nginx start 命令結束后,sh 也就結束了,sh 作為主行程退出了,自然就會令容器退出,
正確的做法是直接執行 nginx 可執行檔案,并且要求以前臺形式運行,比如:
CMD ["nginx", "-g", "daemon off;"]

EXPOSE
宣告埠 EXPOSE <埠1> [<埠2>...]
宣告運行時容器提供服務埠,這只是一個宣告,在運行時并不會因為這個宣告應用就會開啟這個埠的服務,此宣告有兩個好處
1.幫助使用者理解服務的守護埠,以便配置映射.
2.啟動容器時,指定 docker run -P 時,會將EXPOSE 埠映射到物理機的隨機埠.

ENTRYPOINT
當定義了ENTRYPOINT以后,CMD只能夠作為引數進行傳遞.

有2種定義方式:
1.ENTRYPOINT ["executable","arg1","arg2"] (推薦) CMD可以通過json的方式來定義entrypoint的引數,在運行容器的時候可以通過CMD的方式傳遞引數.執行的程式的pid為1.
2.ENTRYPOINT cmd param1 param2 (shell form)  相當于/bin/bash -c "cmd"命令.bash的pid為1.會屏蔽掉docker run時后面加的命令和CMD里的引數.不常用.

示例,第一種,比如:
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
把可能需要變動的引數寫到CMD里面,然后你可以在docker run里指定引數,這樣CMD里的引數(這里是-c)就會被覆寫掉,而ENTRYPOINT里的不會被覆寫,
ENTRYPOINT更像是一個可執行程式,而CMD是隨時都可能被覆寫的命令或傳參.

COPY & ADD
不建議用ADD.
類似于直接在bash里執行的指令是 docker container cp [containID]:[/path/to/file] /local/path/dir/ (容器檔案拷貝到物理機).
把host上的檔案或者目錄(源檔案必須在context路徑下)復制到image中.如果目錄不存在會在復制檔案前先行創建缺失目錄.
不建議使用ADD(因為語意模糊,且沒必要)
ADD相對COPY多的功能(支持URL),當src為網路URL的情況下,ADD指令可以把它下載到dest的指定位置.ADD相對COPY多的功能,能夠進行自動解壓壓縮包.

ENV
ENV 或 ENV = =...
后面的其它指令,如 RUN,還是運行時的應用,都可以直接使用這里定義的環境變數,

WORKDIR
用來改變作業目錄.
比如:
RUN cd /app
RUN echo "hello" > world.txt
這樣做根本不會生成/app/world.txt檔案.原因是,每一個 RUN 都是啟動一個容器、執行命令、然后提交存盤層檔案變更,第一層 RUN cd /app 的執行僅僅是當前行程的作業目錄變更,一個記憶體上的變化而已,其結果不會造成任何檔案變更,而到第二層的時候,啟動的是一個全新的容器,跟第一層的容器更完全沒關系,自然不可能繼承前一層構建程序中的記憶體變化,
因此如果需要改變以后各層的作業目錄的位置,那么應該使用 WORKDIR 指令,

USER
改變之后層的執行 RUN, CMD 以及 ENTRYPOINT 這類命令的身份.
擴展知識: 如果以 root 執行的腳本,在執行期間希望改變身份,比如希望以某個已經建立好的用戶來運行某個服務行程,不要使用 su 或者 sudo,這些都需要比較麻煩的配置,而且在 TTY 缺失的環境下經常出錯,建議使用 gosu,

#建立 redis 用戶,并使用 gosu 換另一個用戶執行命令
RUN groupadd -r redis && useradd -r -g redis redis
#下載 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
#設定 CMD,并以另外的用戶執行
CMD [ "exec", "gosu", "redis", "redis-server" ]    #exec的說明,執行shell腳本三種方式的區別( sh,bash,xxx.sh / source,. / exec ) 見<<shell bash 技巧說明>>筆記.

VOLUME
Dockerfile中的VOLUME使每次運行一個新的container時,都會為其自動創建一個匿名的volume,并掛載到container指定的目錄里.
應用場景: 用來創建一個在image之外的mount point,可以用來在多個container之間實作資料共享(通過--volumes-from嗎?).
運行使用json array的方式定義多個volume.
VOLUME ["/var/data1","/var/data2"] .
或者plain text的情況下定義多個VOLUME指令.

示例,cat Dockerfile

FROM nginx
#VOLUME ["/home/admin/test"] 或 #VOLUME ["/home/admin/test","home/admin/mynginx"] 或
VOLUME /home/admin/test
在docker container run xxx 的時候,會創建一個匿名volume.比如,物理機上的/var/lib/docker/volumes/99b2...d1/_data -> 容器內的/home/admin/test .

在 Dockerfile 中添加資料卷
在 Dockerfile 中我們可以使用 VOLUME 指令向容器添加資料卷:

VOLUME /data     # 這里只跟容器有關,因為為了匹配不同物理機卷環境,所以物理機卷必是匿名卷.

在使用 docker build 命令生成鏡像并且以該鏡像啟動容器時會掛載一個主機資料卷到容器 /data 目錄,根據我們已知的資料覆寫規則,如果鏡像中存在 /data 目錄,鏡像中的/data目錄的內容將全部被復制到宿主機中對應的目錄中(匿名目錄),并且根據容器中的檔案設定合適的權限和所有者,假設在docker run 的時候,添加 -v /data:/data(前一個是物理主機目錄,且有資料,后一個是新啟動容器目錄) ,會發生什么呢?應該會以物理機資料優先吧.
注意,VOLUME 指令不能掛載主機中指定的目錄,這是為了保證 Dockerfile 的一致性,因為不能保證所有的宿主機都有對應的目錄,

在實際的使用中,這里還有一個陷阱需要大家注意:在 Dockerfile 中使用 VOLUME 指令之后的代碼,如果嘗試對這個資料卷進行修改,這些修改都不會生效!下面是一個這樣的例子:

FROM ubuntu
RUN useradd nick
VOLUME /data    # 其實把VOLUME當做宣告就可以了,不實際創建卷.這樣理解.
RUN touch /data/test.txt
RUN chown -R nick:nick /data

通過這個 Dockerfile 創建鏡像并啟動容器后,該容器中存在用戶 nick,并且能夠看到 /data 目錄掛載的資料卷,但是 /data 目錄內并沒有檔案 test.txt,更別說 test.txt 檔案的所有者屬性了,要解釋這個現象需要我們了解通過 Dockerfile 創建鏡像的程序:
Dockerfile 中除了 FROM 指令的每一行都是基于上一行生成的臨時鏡像運行一個容器,執行一條指令并執行類似 docker commit 的命令得到一個新的鏡像,這條類似 docker commit 的命令不會對掛載的資料卷進行保存,
所以上面的 Dockerfile 最后兩行執行時,都會在一個臨時的容器上掛載 /data,并對這個臨時的資料卷進行操作,但是這一行指令執行并提交后,這個臨時的資料卷并沒有被保存,因而我們最終通過鏡像創建的容器所掛載的資料卷是沒有被最后兩條指令操作過的,我們姑且叫它 "Dockerfile 中資料卷的初始化問題",
下面的寫法可以解決 Dockerfile 中資料卷的初始化問題:

FROM ubuntu
RUN useradd nick
RUN mkdir /data && touch /data/test.txt # 創建了/data目錄
RUN chown -R nick:nick /data
VOLUME /data    # 在宣告前,鏡像里已經有/data目錄了,那么會將目錄以及內容復制到啟動的容器匿名目錄里(對應容器的/data目錄).

通過這個 Dockerfile 創建鏡像并啟動容器后,資料卷的初始化是符合預期的,這是由于在掛載資料卷時,/data 已經存在,/data 中的檔案以及它們的權限和所有者設定會被復制到資料卷中(被復制到物理主機的匿名卷中,對應的就是新啟動的容器的/data目錄),
還有另外一種方法可以解決 Dockerfile 中資料卷的初始化問題,就是利用 CMD 指令和 ENTRYPOINT 指令的執行特點:與 RUN 指令在鏡像構建程序中執行不同,CMD 指令和 ENTRYPOINT 指令是在容器啟動時執行,因此使用下面的 Dockerfile 也可以達到對資料卷的初始化目的:

FROM ubuntu
RUN useradd nick
VOLUME /data
CMD touch /data/test.txt && chown -R nick:nick /data && /bin/bash

HEALTHCHECK
健康檢查

ONBUILD:略

如何撰寫最佳的Dockerfile(基本為網上內容)
目標:

  • 更快的構建速度
  • 更小的Docker鏡像大小
  • 更少的Docker鏡像層
  • 充分利用鏡像快取
  • 增加Dockerfile可讀性
  • 讓Docker容器使用起來更簡單

總結(撰寫Dockerfile需要注意的問題)

  • 撰寫.dockerignore檔案
  • 容器只運行單個應用
  • 將多個RUN指令合并為一個
  • 基礎鏡像的標簽不要用latest
  • 每個RUN指令后洗掉多余檔案
  • 選擇合適的基礎鏡像(alpine版本最好)
  • 設定WORKDIR和CMD
  • 使用ENTRYPOINT (可選)
  • 在entrypoint腳本中使用exec
  • COPY與ADD優先使用前者
  • 合理調整COPY與RUN的順序
  • 設定默認的環境變數,映射埠和資料卷
  • 使用LABEL設定鏡像元資料
  • 添加HEALTHCHECK

示例
最初示例
示例Dockerfile犯了幾乎所有的錯.假設我們需要使用Docker運行一個Node.js應用,下面就是它的Dockerfile(CMD指令太復雜了,所以我簡化了,它是錯誤的,僅供參考),

FROM ubuntu
ADD . /app
RUN apt-get update  
RUN apt-get upgrade -y  
RUN apt-get install -y nodejs ssh mysql  
RUN cd /app && npm install
# this should start three processes, mysql and ssh
# in the background and node app in foreground
# isn't it beautifully terrible? <3
CMD mysql & sshd & npm start #這里是錯誤的

構建鏡像:
docker build -t wtf .

這里先給出最終示例(對比):

FROM node:7-alpine
ENV PROJECT_DIR=/app
WORKDIR $PROJECT_DIR
COPY package.json $PROJECT_DIR  
RUN npm install  
COPY . $PROJECT_DIR
ENV MEDIA_DIR=/media \  
    NODE_ENV=production \
    APP_PORT=3000
VOLUME $MEDIA_DIR  
EXPOSE $APP_PORT
ENTRYPOINT ["./entrypoint.sh"]  
CMD ["start"]

將最初示例逐步進行優化的程序

  1. 撰寫.dockerignore檔案
    構建鏡像時,Docker需要先準備context ,將所有需要的檔案收集到行程中,默認的context包含Dockerfile目錄中的所有檔案,但是實際上,我們并不需要.git目錄,node_modules目錄等內容,示例如下:
    .git/
    node_modules/

  2. 容器只運行單個應用
    因此,我建議大家為每個應用構建單獨的Docker鏡像,然后使用 Docker Compose 運行多個Docker容器,
    現在,我從Dockerfile中洗掉一些不需要的安裝包,另外,SSH可以用docker exec替代,示例如下:

FROM ubuntu
ADD . /app
RUN apt-get update  
RUN apt-get upgrade -y
# we should remove ssh and mysql, and use
# separate container for database
RUN apt-get install -y nodejs  # ssh mysql  
RUN cd /app && npm install
CMD npm start
  1. 將多個RUN指令合并為一個
    Docker鏡像是分層的.Docker鏡像類似于洋蔥,它們都有很多層,為了修改內層,則需要將外面的層都刪掉,記住這一點的話,其他內容就很好理解了,
    現在,我們將所有的RUN指令合并為一個,
    記住一點,我們只能將變化頻率一樣的指令合并在一起,將node.js安裝與npm模塊安裝放在一起的話,則每次修改源代碼,都需要重新安裝node.js,這顯然不合適.

  2. 基礎鏡像的標簽不要用latest
    當鏡像沒有指定標簽時,將默認使用latest 標簽,當鏡像更新時,latest標簽會指向不同的鏡像,這時構建鏡像有可能失敗,
    示例Dockerfile應該使用16.04作為標簽,

  3. 每個RUN指令后洗掉多余檔案
    假設我們更新了apt-get源,下載,解壓并安裝了一些軟體包,它們都保存在/var/lib/apt/lists/目錄中,但是,運行應用時Docker鏡像中并不需要這些檔案,我們最好將它們洗掉,因為它會使Docker鏡像變大,
    示例Dockerfile中,我們可以洗掉/var/lib/apt/lists/目錄中的檔案(它們是由apt-get update生成的),

FROM ubuntu:16.04
RUN apt-get update \  
    && apt-get install -y nodejs \
    # added lines
    && rm -rf /var/lib/apt/lists/*
ADD . /app  
RUN cd /app && npm install
CMD npm start
  1. 選擇合適的基礎鏡像(alpine版本最好)
    在示例中,我們選擇了ubuntu作為基礎鏡像,但是我們只需要運行node程式,有必要使用一個通用的基礎鏡像嗎?node鏡像應該是更好的選擇,
    FROM node
    ...
    更好的選擇是alpine版本的node鏡像,alpine是一個極小化的Linux發行版,只有4MB,這讓它非常適合作為基礎鏡像,
FROM node:7-alpine
ADD . /app  
RUN cd /app && npm install
CMD npm start
  1. 設定WORKDIR和 CMD
    WORKDIR指令可以設定默認目錄,也就是運行RUN / CMD / ENTRYPOINT指令的地方,
    CMD指令可以設定容器創建時執行的默認命令,另外,你應該將命令寫在一個陣列中,陣列中每個元素為命令的每個單詞.
FROM node:7-alpine
WORKDIR /app  
ADD . /app  
RUN npm install
CMD ["npm", "start"]
  1. 使用ENTRYPOINT (可選)
    ENTRYPOINT指令并不是必須的,因為它會增加復雜度,
    ENTRYPOINT可以是一個腳本,會默認執行,它通常用于構建可執行的Docker鏡像,
    示例Dockerfile:
FROM node:7-alpine
WORKDIR /app  
ADD . /app  
RUN npm install
ENTRYPOINT ["./entrypoint.sh"]  #該腳本可以接受dev,start,*等引數.
CMD ["start"]

可以使用如下命令運行該鏡像:
# 運行開發版本    docker run our-app dev
# 運行生產版本    docker run our-app start
# 運行bash版本    docker run -it our-app /bin/bash
  1. 在entrypoint腳本中使用exec
    在前文的entrypoint腳本中,我使用了exec命令運行node應用,不使用exec的話,我們則不能順利地關閉容器,因為SIGTERM信號會被bash腳本行程吞沒,exec命令啟動的行程可以取代腳本行程,因此所有的信號都會正常作業,

  2. COPY與ADD優先使用前者
    COPY指令非常簡單,僅用于將檔案拷貝到鏡像中,ADD相對來講復雜一些,可以用于下載遠程檔案以及解壓壓縮包.

FROM node:7-alpine
WORKDIR /app
COPY . /app  
RUN npm install
ENTRYPOINT ["./entrypoint.sh"]  
CMD ["start"]
  1. 合理調整COPY與RUN的順序
    我們應該把變化最少的部分放在Dockerfile的前面,這樣可以充分利用鏡像快取,
    示例中,源代碼會經常變化,則每次構建鏡像時都需要重新安裝NPM模塊,這顯然不是我們希望看到的,因此我們可以先拷貝package.json,然后安裝NPM模塊,最后才拷貝其余的源代碼,這樣的話,即使源代碼變化,也不需要重新安裝NPM模塊,
FROM node:7-alpine
WORKDIR /app
COPY package.json /app  
RUN npm install  
COPY . /app
ENTRYPOINT ["./entrypoint.sh"]  
CMD ["start"]
  1. 設定默認的環境變數,映射埠和資料卷(相對于上面的11項,這里比較完整歸納了上面遇到的問題)
    運行Docker容器時很可能需要一些環境變數,在Dockerfile設定默認的環境變數是一種很好的方式,
    另外,我們應該在Dockerfile中設定映射埠和資料卷,
    示例如下:
FROM node:7-alpine
ENV PROJECT_DIR=/app
WORKDIR $PROJECT_DIR
COPY package.json $PROJECT_DIR  
RUN npm install  
COPY . $PROJECT_DIR
ENV MEDIA_DIR=/media \  
    NODE_ENV=production \
    APP_PORT=3000
VOLUME $MEDIA_DIR  
EXPOSE $APP_PORT
ENTRYPOINT ["./entrypoint.sh"]  
CMD ["start"]

ENV指令指定的環境變數在容器中可以使用,如果你只是需要指定構建鏡像時的變數,你可以使用ARG指令,

  1. 使用LABEL設定鏡像元資料
    使用LABEL指令,可以為鏡像設定元資料,例如鏡像創建者或者鏡像說明,
    舊版的Dockerfile語法使用MAINTAINER指令指定鏡像創建者,但是它已經被棄用了,
    有時,一些外部程式需要用到鏡像的元資料,例如nvidia-docker需要用到com.nvidia.volumes.needed,
    示例如下:
    FROM node:7-alpine
    LABEL maintainer "[email protected]"
    ...

  2. 添加HEALTHCHECK
    運行容器時,可以指定--restart always選項,這樣的話,容器崩潰時,Docker守護行程(docker daemon)會重啟容器,對于需要長時間運行的容器,這個選項非常有用,但是,如果容器的確在運行,但是不可(陷入死回圈,配置錯誤)用怎么辦?使用HEALTHCHECK指令可以讓Docker周期性的檢查容器的健康狀況,我們只需要指定一個命令,如果一切正常的話回傳0,否則回傳1,
    示例如下:

FROM node:7-alpine  
LABEL maintainer "[email protected]"
...
EXPOSE $APP_PORT  
HEALTHCHECK CMD curl --fail http://localhost:$APP_PORT || exit 1
ENTRYPOINT ["./entrypoint.sh"]  
CMD ["start"]

當請求失敗時,curl --fail 命令回傳非0狀態,

docker compose 單主機容器編排

20180728 Chenxin
Docker是容器技術的核心、基礎.
Docker Compose是一個基于Docker的單主機容器編排工具,功能并不像Docker Swarm和Kubernetes是基于Dcoker的跨主機的容器管理平臺那么豐富,

這個也挺常用的,將一組服務的多個docker一起管理.具體需要深入研究
你說多服務?好吧那就寫個docker-compose.file吧, 嗯哼? 你說集群部署 來來來, 有Kubernetes、Mesos,Fleet和Swarm 任君挑選
https://docs.docker.com/compose/
https://blog.csdn.net/pushiqiang/article/details/78682323
https://www.cnblogs.com/neptunemoon/p/6512121.html

Compose 中有兩個重要的概念:
服務 (service):一個應用的容器,實際上可以包括若干運行相同鏡像的容器實體,
專案 (project):由一組關聯的應用容器組成的一個完整業務單元,在 docker-compose.yml 檔案中定義,
Compose 的默認管理物件是專案,通過子命令對專案中的一組容器進行便捷地生命周期管理,

安裝:
pip install docker-compose 如果報錯,添加引數 --ignore-installed docker-compose

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/60091.html

標籤:其他

上一篇:三大運營商的云計算之殤

下一篇:可能是國內第一篇全面解讀 Java 現狀及趨勢的文章

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more