1.介紹
????????Docker 提供了一種更便捷的方式,叫作 Dockerfile,docker build命令用于根據給定的Dockerfile構建Docker鏡像。
docker build語法: # docker build [OPTIONS] <PATH | URL | ->
常用選項說明
--build-arg,設置構建時的變量
--no-cache,默認false。設置該選項,將不使用Build Cache構建鏡像
--pull,默認false。設置該選項,總是嘗試pull鏡像的最新版本
--compress,默認false。設置該選項,將使用gzip壓縮構建的上下文
--disable-content-trust,默認true。設置該選項,將對鏡像進行驗證
--file, -f,Dockerfile的完整路徑,默認值為‘PATH/Dockerfile’
--isolation,默認--isolation="default",即Linux命名空間;其他還有process或hyperv
--label,為生成的鏡像設置metadata
--squash,默認false。設置該選項,將新構建出的多個層壓縮為一個新層,但是將無法在多個鏡像之間共享新層;設置該選項,實際上是創建了新image,同時保留原有image。
--tag, -t,鏡像的名字及tag,通常name:tag或者name格式;可以在一次構建中為一個鏡像設置多個tag
--network,默認default。設置該選項,Set the networking mode for the RUN instructions during build
--quiet, -q ,默認false。設置該選項,Suppress the build output and print image ID on success
--force-rm,默認false。設置該選項,總是刪除掉中間環節的容器
--rm,默認--rm=true,即整個構建過程成功后刪除中間環節的容器示例:?
docker build -t newrain/bbauto:v2.1 .docker build ?是docker創建鏡像的命令?
-t 是標識新建的鏡像屬于 newrain的 bbauto鏡像?
:v2 是tag?
"."是用來指明 我們的使用的Dockerfile文件當前目錄的?
2.?創建鏡像
2.1、 創建鏡像所在的文件夾和Dockerfile文件
[root@docker ~]# mkdir sinatra
[root@docker ~]# cd sinatra/
[root@docker sinatra]# touch Dockerfile
2.2、 在Dockerfile文件中寫入指令,每一條指令都會更新鏡像的信息例如:
[root@docker sinatra]# vim Dockerfile
#This is a comment
FROM daocloud.io/library/centos:7
MAINTAINER newrain newrain@docker
RUN yum install -y wget
RUN touch a.txt
RUN mkdir /test
命令要大寫,"#"是注解。?
每一個指令后面需要跟空格,語法。
FROM 命令是告訴docker 我們的鏡像什么從哪里下載。?
MAINTAINER 是描述 鏡像的創建人。 ? maintainer
RUN 命令是在鏡像內部執行。就是說他后面的命令應該是針對鏡像可以運行的命令。??
? 2.3、創建鏡像
命令:
# docker build -t newrain/centso:7 .?docker build ?是docker創建鏡像的命令 ?
2.4、創建完成后,從鏡像創建容器
3.?Dockerfile實例:容器化python的flask應用
????????實戰練習
1.創建一個nginx的dockerfile
[root@docker ~]# mkdir nginx
[root@docker ~]# cd nginx/
[root@docker nginx]# vim Dockerfile
# This my first nginx Dockerfile
# Version 1.0
FROM daocloud.io/library/centos:7
MAINTAINER docker
ENV PATH /usr/local/nginx/sbin:$PATH
ADD nginx-1.16.1.tar.gz /usr/local/
ADD epel-release-7-11.noarch.rpm /usr/local/
RUN rpm -ivh /usr/local/epel-release-7-11.noarch.rpm
RUN yum install -y gcc gcc-c++ make && yum -y install openssl openssl-devel && yum install -y zlib zlib-devel && yum clean all
RUN useradd -s /sbin/nologin -M www
WORKDIR /usr/local/nginx-1.16.1
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www && make && make install
RUN echo "daemon off;" >> /etc/nginx.conf
EXPOSE 80
CMD /bin/sh -c 'nginx -g "daemon off;"' #放前臺啟動[root@docker nginx]# ls #將nginx的tar包與epel源上傳到nginx目錄下面
Dockerfile epel-release-7-11.noarch.rpm nginx-1.16.1.tar.gz
[root@docker nginx]# pwd
/root/nginx
[root@docker nginx]# docker build -t nginx:v7.1 .
[root@docker nginx]# docker run -itd --name nginx9 -p 8088:80 nginx:v7.1 #啟動容器
[root@docker nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fec1f3a37cb0 nginx:v7.1 "/bin/sh -c '/bin/sh…" 6 seconds ago Up 5 seconds 0.0.0.0:8088->80/tcp
2.創建一個jenkins的Dockerfile
[root@docker ~]# mkdir tomcat
[root@docker ~]# cd tomcat/
[root@docker tomcat]# vim Dockerfile
# This my first jenkins Dockerfile
# Version 1.0
FROM daocloud.io/library/centos:7
MAINTAINER docker
ENV JAVA_HOME /usr/local/jdk1.8.0_211
ENV TOMCAT_HOME /usr/local/apache-tomcat-8.5.47
ENV PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
ADD apache-tomcat-8.5.47.tar.gz /usr/local/
ADD jdk-8u211-linux-x64.tar.gz /usr/local/
RUN rm -rf /usr/local/apache-tomcat-8.5.47/webapps/*
ADD jenkins.war /usr/local/apache-tomcat-8.5.47/webapps
RUN rm -rf apache-tomcat-8.5.47.tar.gz apache-tomcat-8.5.47.tar.gz
EXPOSE 8080
ENTRYPOINT ["/usr/local/apache-tomcat-8.5.47/bin/catalina.sh","run"] #運行的命令
[root@docker tomcat]# pwd
/root/tomcat
[root@docker tomcat]# ls #將jdk與tomcat還有jenkins的包上傳到tomcat目錄中
apache-tomcat-8.5.47.tar.gz Dockerfile jdk-8u211-linux-x64.tar.gz jenkins.war
[root@docker tomcat]# docker build -t jenkins:v1 .
[root@docker tomcat]# docker run -itd --name jenkins1 -p 8081:8080 jenkins:v1
????????擴展----CMD與ENTRYPOINT區別
一、dockerfile中的 CMD
1、每個dockerfile中只能有一個CMD如果有多個那么只執行最后一個。
2、CMD 相當于啟動docker時候后面添加的參數看,舉個簡單例子:
# docker run -itd --name test image(鏡像) /bin/bash -c
a、鏡像名稱后面跟了一個/bin/bash -c ,其實等價于在dockerfile中的CMD ["/bin/bash","-c"]。
b、如果dockerfile中的CMD中有了CMD["/bin/bash","-c"],那么就不用在執行的時候再添加了,如果添加了參數的話那么就相當于要執行你添加的參數,默認的CMD中的參數就無效了。二、dockerfile中的ENTRYPOINT
1、一個dockerfile中ENTRYPOINT也只能存在一個,若存在多個那么只執行最后一個,你可以理解為開機啟動的意思,和CMD有點像,不過還是有區別。2、舉個簡單例子:
a、dockerfile中有ENTRYPOINT ["tail","-f","/var/log/nginx/access.log"],那么啟動的時候鏡像就執行了這個里面的內容,如果你像上面帶參數的話就相當于在這個執行的內容后面再加入參數。
案例:
如果我們的dockerfile中有a中的這句話然后我們啟動我們的docker:
#docker run -itd --name test image(鏡像名) /bin/bash -c此時就相當于我們啟動docker的時候執行了:tail -f /var/log/nginx/access.log /bin/bash -c
這個命令明顯就不對.
?????????dockerfile優化
1、RUN 命令要盡量寫在一條里,每次 RUN 命令都是在之前的鏡像上封裝,只會增大不會減小
2、每次進行依賴安裝后,記得yum clean all【centos】?
#yum clean all 清除緩存中的rpm頭文件和包文件
3、選擇比較小的基礎鏡像。alpine
4.部署私有倉庫應用
????????私有倉庫鏡像:
????????registry --官方出品, 沒有圖形界面.Docker hub官方已提供容器鏡像registry,用于搭建私有倉庫,拉取鏡像:
[root@docker ~]# docker pull daocloud.io/library/registry:latest
????????運行容器:
[root@docker ~]# docker run -d -v /home/dockerdata/registry:/var/lib/registry --name "pri_registry" --restart=always -p 5000:5000 daocloud.io/library/registry參數解釋:
/home/dockerdata/registry表示為宿主機的目錄,如果不存在自動創建
-v映射目錄: 宿主機的目錄:容器目錄
把宿主機的目錄掛載到容器中,將數據目錄掛載出來就是為了防止docker私有倉庫這個容器被刪除的時候,倉庫里面的鏡像也被刪除。
-p 端口映射:本地端口:容器端口
????????注:如果創建容器不成功,報錯防火墻,解決方案如下
#systemctl stop firewalld
#yum install iptaqbles*
#systemctl start iptables
#iptables -F
#systemctl restart docker
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0823df72b160 daocloud.io/library/registry "/entrypoint.sh /etc…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp pri_registry
????????連接容器查看端口狀態:
[root@docker ~]# docker exec -it 0823df7 /bin/sh
/ # netstat -lntp #查看5000端口是否開啟
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 :::5000 :::* LISTEN 1/registry
/ #
?????????在本機查看能否訪問該私有倉庫, 看看狀態碼是不是200:
[root@docker ~]# curl -I http://127.0.0.1:5000
HTTP/1.1 200 OK
????????為了方便,下載1個比較小的鏡像,buysbox
[root@docker ~]# docker pull daocloud.io/library/busybox
????????上傳前必須給鏡像打tag 注明ip和端口:
[root@docker ~]# docker tag busybox 192.168.246.141:5000/busybox
宿主機查看目錄:
[root@docker ~]# ls /home/dockerdata/registry/docker/registry/v2/repositories/
???????? 下面這個Mysql是我測試的第二個鏡像,從daocloud拉取的:
[root@docker ~]# docker pull daocloud.io/library/mysql
[root@docker ~]# docker tag daocloud.io/library/mysql 192.168.246.141:5000/daocloud.io/library/mysql
[root@docker ~]# docker images
????????注:tag后面可以使用鏡像名稱也可以使用id,我這里使用的鏡像名稱,如果使用官方的鏡像,不需要加前綴,但是daocloud.io的得加前綴.
????????修改請求方式為http:
默認為https,不改會報以下錯誤:
Get https://master.up.com:5000/v1/_ping: http: server gave HTTP response to HTTPS client[root@docker ~]# vim /etc/docker/daemon.json #不存在則創建
{ "insecure-registries":["192.168.246.141:5000"] }重啟docker:
[root@docker ~]# systemctl restart docker
????????上傳鏡像到私有倉庫:
[root@docker ~]# docker push 192.168.246.141:5000/busybox
[root@docker ~]# docker push 192.168.246.141:5000/daocloud.io/library/mysql
????????查看私有倉庫里的所有鏡像:
語法: # curl http://ip:port/v2/repo名字/tags/list
[root@docker ~]# curl http://192.168.246.141:5000/v2/busybox/tags/list
{"name":"busybox","tags":["latest"]}[root@docker ~]# curl http://192.168.246.141:5000/v2/daocloud.io/library/mysql/tags/list
{"name":"daocloud.io/library/mysql","tags":["latest"]} 這條命令會查看倉庫下面所有的鏡像:
[root@docker ~]# curl http://192.168.246.141:5000/v2/_catalog
????????拉取鏡像測試:
1.先將剛才打了tags的鏡像刪掉
[root@docker ~]# docker rmi 192.168.246.141:5000/busybox
2.拉取鏡像:
[root@docker ~]# docker pull 192.168.246.141:5000/busybox
[root@docker ~]# docker images