Docker 部署項目
一、安裝docker(Ubuntu)
轉自:https://blog.csdn.net/jinking01/article/details/82490688
- 由於apt官方庫里的docker版本可能比較舊,所以先卸載可能存在的舊版本:
$ sudo apt-get remove docker docker-engine docker-ce docker.io
- 更新apt包索引:
$ sudo apt-get update
- 安裝以下包以使apt可以通過HTTPS使用存儲庫(repository):
$ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
- 添加Docker官方的GPG密鑰:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 使用下面的命令來設置stable存儲庫:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- 再更新一下apt包索引:
$ sudo apt-get update
- 安裝最新版本的Docker CE:
$ sudo apt-get install -y docker-ce
- 驗證docker
$ systemctl status docker
docker正常啟動,狀態如下圖:
- 若未啟動,則啟動docker服務:
$ sudo systemctl start docker
- 查看docker版本號驗證
$ sudo docker -v
二、docker倉庫配置
1、設置公有倉庫
- 修改倉庫配置文件
$ vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
- 重啟docker
$ systemctl daemon-reload
$ systemctl restart docker
常用國內加速站點:
https://registry.docker-cn.com 國內
http://hub-mirror.c.163.com 網易
https://3laho3y3.mirror.aliyuncs.com 阿里
http://f1361db2.m.daocloud.io
https://mirror.ccs.tencentyun.com
2、設置私有倉庫
參考:https://www.cnblogs.com/xiao987334176/p/9946915.html
1)搭建私有倉庫——私有服務器上
- 搭建工具
docker 官方提供了 registry
的鏡像,可以使用它來建私有倉庫。
- 環境
系統 | IP | 角色 |
---|---|---|
Ubuntu 18.04 | 10.0.0.0 | docker 客戶端服務器 |
Ubuntu 18.04 | 10.0.0.1 | docker 倉庫服務器(root用戶) |
-
都安裝docker,修改docker源,並重啟(參考一)
-
在10.0.0.1上拉取
registry
docker pull registry
-
在10.0.0.1上啟動倉庫
docker run -d --name docker-registry --restart=always -p 5000:5000 registry
2)設置私有倉庫
-
客戶端10.0.0.0設置私有倉庫地址,並重啟
$ vim /etc/docker/daemon.json
{ "registry-mirrors": ["https://registry.docker-cn.com"], "insecure-registries": ["10.0.0.1:5000"] # 設置私有倉庫地址 }
systemctl restart docker
-
測試私有倉庫
在10.0.0.0下載一個鏡像,如alpine
sudo docker pull alpine
打tag,鏡像名稱由registry和tag兩部分組成,registry完整格式:
[registry_ip]:[registry:port]/[user]/[image_name:version]
sudo docker tag alpine 10.0.0.1:5000/alpine
-
上傳本地鏡像
sudo docker push 10.0.0.1:5000/alpine
-
查看倉庫鏡像
curl 10.0.0.1:5000/v2/_catalog
三、拉取鏡像
1、登錄倉庫
sudo docker login -u [user] -p [password] [ip:port]
- user 倉庫用戶名
- password 倉庫密碼
- ip:port為倉庫地址
2、拉取鏡像
sudo docker pull [image_name]
四、dockerfile編寫
在項目目錄下創建Dockerfile
文件
參考:https://www.cnblogs.com/cloudfloating/p/11737447.html
1、RUN
RUN
指令是用來執行命令行命令的。RUN
指令的格式有兩種:
-
shell 格式:
RUN <命令>
,就像直接在命令行中輸入命令一樣。RUN java -jar app.jar
-
exec 格式:
RUN ["可執行文件", "參數1", "參數2"]
。RUN ["java", "-jar", "app.jar"]
在 Dockerfile
中,每一個指令都會在鏡像上建立一層,所以對於多個命令行,不要寫多個 RUN
指令。
多個命令,在一個RUN中實現,使用 **&&
**連接起來
FROM ubuntu
RUN apt-get update \
&& apt-get install -y redis
2、COPY
COPY
指令用來將宿主的文件目錄復制到鏡像中。有兩種格式:
-
COPY [--chown=<user>:<group>] <源路徑>... <目標路徑>
COPY app.jar /usr/src/
-
COPY [--chown=<user>:<group>] ["源路徑1", ... "目標路徑"]
COPY ["app.jar", "config.yml", "/usr/src"]
對於多個路徑參數,最后一個為目標路徑,其他都是源路徑。目標路徑
可以是絕對路徑,也可以是相對於工作目錄的路徑(工作目錄可以用 WORKDIR
來指定)。目標路徑如果不存在,在復制文件前會先創建。
3、CMD
CMD
是容器啟動命令,它指定了容器啟動后要執行的程序。與 RUN
指令相似有兩種形式:
-
shell 格式:
CMD <命令>
CMD echo 'Hello, world!''
-
exec 格式:
CMD ["可執行文件", "參數1", "參數2", ...]
CMD [ "sh", "-c", "echo 'Hello, world!'" ]
還有一種參數列表格式:CMD ["參數1", "參數2", ...]
。在指定了 ENTRYPOINT
指令后,可以用 CMD
指定參數。
在使用 CMD
時,程序必須以前台運行,Docker 不是虛擬機,容器沒有后台服務的概念。如果使用 CMD
運行一個后台程序,那么容器在命令執行完就會退出。
CMD java -jar app.jar &
以上命令讓 app.jar 在后台運行,容器啟動后就會立刻退出。Docker 容器與守護線程很相似,當所有前台程序退出后,容器就會退出。
CMD
指定的命令可以在運行時替換,跟在鏡像名稱后面的參數將替換鏡像中的 CMD
。
docker run app echo $HOME
以上命令運行容器時使用 echo $HOME
替換掉鏡像中的啟動命令。
4、ENV
ENV
指令用來設置環境變量,格式有兩種:
ENV <key> <value
ENV <key1>=<value1> <key2>=<value2>
環境變量在后面的其它指令中可以通過 $key
來使用:
FROM ubuntu
ENV VERSION="8-jre"
RUN apt-get update \
&& apt-get install -y openjdk-$VERSION
...
5、ARG
ARG
指令指定構建參數,與 ENV
效果一樣,都是設置環境變量。不同的是,ARG
設置的構建參數,在容器運行時不存在。
格式:ARG <key>[=<默認值>]
,可以指定默認值,也可以不指定。
FROM alpine
ARG NAME="Hello, Docker!"
RUN echo $NAME
CMD echo $NAME
對於以上 Dockerfile
,在構建時可以看到輸出,但是在運行容器時沒有輸出。
ARG
設置的參數可以在構建命令中指定:docker build --build-arg <key>=<value>
。
6、VOLUME
VOLUME
指令用來定義匿名卷。
VOLUME <路徑>
VOLUME ["路徑1", "路徑2", ...]
對於數據庫類需要保持數據的應用,其文件應該保存於卷(volume)中,在 Dockerfile
中,可以事先將指定的目錄掛載為匿名卷。
VOLUME /data
這里 /data
目錄在容器運行時自動掛載為匿名卷,任何寫入 /data
中的數據都不會記錄到容器的存儲層。在運行時可以覆蓋這個掛載設置:
docker run -v dbdir:/data
以上命令將 dbdir
目錄掛載到了 /data
,替換了 Dockerfile
中的掛載配置。
7、EXPOSE
EXPOSE
指令指定容器運行時暴露的端口。格式:EXPOSE <端口1> [<端口2> ...]
。
FROM ubuntu
EXPOSE 8080
RUN apt-get update \
&& apt-get install -y tomcat8
...
以上 Dockerfile
安裝了 tomcat 應用,在運行容器時會暴露 8080 端口。
EXPOSE
只是指定了容器暴露的端口,並不會在宿主機進行端口映射。在使用 docker run -P
時,會自動隨機映射 EXPOSE
指定的端口,也可以使用 -p
指定端口:docker run -p <宿主端口>:<容器端口>
。
8、WORKDIR
WORKDIR
指令指定工作目錄,即指定當前目錄,類似於 cd
命令,以后各層的當前目錄都是 WORKDIR
指定的目錄。如果目錄不存在,會自動創建。格式:WORKDIR <目錄路徑>
。
不能把 Dockerfile
當成 Shell 腳本來寫:
RUN cd /src/app
RUN java -jar app.jar
以上操作中第二行的工作目錄並不是 /src/app
,兩個指令不在同一層,第一個 RUN
指令的 cd
操作和第二個沒有任何關系。因此要切換目錄,應該使用 WORKDIR
來指定。
9、USER
USER
指令指定當前用戶。與 WORKDIR
相似,會影響以后的層。USER
改變執行 RUN
、CMD
和 ENTRYPOINT
的用戶。格式:USER <用戶名>[:<用戶組>]
。
USER
指定的用戶和組必須是事先創建好的,否則無法切換。
# 添加用戶
RUN groupadd -r redis \
&& useradd -r -g redis redis
USER redis
ENTRYPOINT ["reids-server"]
10、ONBUILD
ONBUILD
指令后面跟的是其它指令,它在當前鏡像構建時不會被執行,只有以當前鏡像為基礎鏡像去構建下一級鏡像時才會被執行。格式:ONBUILD <其它指令>
。
FROM openjdk:8-jre-alpine
WORKDIR /app
ONBUILD COPY ./app.jar /app
...
這個 Dockerfile
在構建時不會執行 ONBUILD
。
FROM my-jre
...
假設之前構建的鏡像名是 my-jre,以上 Dockerfile
構建鏡像時,原來的 ONBUILD
將執行。
11、ENTRYPOINT
ENTRYPOINT
的格式與 CMD
一樣有兩種格式。
它和 CMD
一樣都是指定容器啟動的程序和參數,但稍有區別。當指定了 ENTRYPOINT
后,CMD
的內容將作為參數加到 ENTRYPOINT
后面。
也就是變成了:
<ENTRYPOINT> "<CMD>"
ENTRYPOINT
可以讓鏡像像命令一樣使用,當僅僅使用 CMD
時,run
命令中鏡像名后面的參數會替換 CMD
的內容。使用 ENTRYPOINT
后,這些參數將附加到原來命令的后面。
FROM alpine
ENTRYPOINT [ "ls" ]
使用以上 Dockerfile
構建的鏡像運行容器:
docker run app -al
-al
參數將附加到 ENTRYPOINT
指定的命令后面,當容器啟動時執行的是 ls -al
。
12、Dockerfile案例
FROM ubuntu:18.04 # 從倉庫拉取一個Ubuntu 18.04的進項
WORKDIR /root # 容器中的工作目錄
RUN apt-get update && \
apt-get install -y vim python3 python3-pip language-pack-zh* mysql-client # 容器中安裝環境
RUN python3 -m pip install -r /root/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ # 容器中安裝項目依賴
五、docker安裝MySQL
1、下載指定版本鏡像
docker pull mysql:8.0.21
2、啟動容器
cd /home/up/docker_test # 進入掛載文件
docker run -p 3307:3306 --name mysql-8 -v $PWD/mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hf1234 -d mysql:8.0.21 # $PWD 表示當前目錄下
-p:表示端口映射,冒號左面的是宿主機的端口,而右側則表示的是MySQL容器內的端口
--name:給MySQL容器取的名字
-d:表示后台運行
-e MYSQL_ROOT_PASSWORD:設置root用戶密碼
-v:表示掛載路徑,冒號左面的表示宿主機的掛載目錄,冒號右邊則表示容器內部的路徑。
3、進入容器
docker exec -it mysql-8 bash
msyql -uroot -p # 登錄數據庫
可能出現的錯誤:
4、可設置遠程訪問
use mysql;
select host,user from user;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '<root_password>';
flush privileges;
六、docker容器間通信
如果在同一個主機上,MySQL為一個容器,django項目為另一個容器,那么就需要兩個容器能夠互相訪問
1、案例
django應用容器,MySQL容器
cd /home/xx/docker_recoder # 宿主機掛載目錄
xx@xx: /home/xx/docker_recoder: $ docker run -d --name mysqlserver -v $PWD/mysql/mysql_data:/var/lib/mysql -p3307:3306 mysql:latest # 運行MySQL容器
xx@xx: /home/xx/docker_recoder: $ docker run -d --name django-web -v $PWD/web/logs:/root/web/logs -p8001:8000 django_web:1.0 # 啟動django應用容器,$PWD表示當前目錄
注意事項
-
在django中MySQL的host用MySQL容器內部的 ip,port為容器內部的port(3306),
- 可通過
docker inspect mysqlserver
查看容器信息,無需安裝工具 - 可通過進入容器后,
ifconfig
獲取容器ip,但是需要安裝ifconfig,如下第三點所示安裝方法
- 可通過
-
查看容器間能否通信,可以
ping <container ip>
,能ping通說明能通信ping 172.17.0.3
-
如果無
ping
、ifconfig
等工具# 安裝ping apt-get install inetutils-ping # 安裝ifconfig apt-get install net-tools
2、實現同主機容器間通信
在安裝好docker后,docker將創建一個linux網橋docker0,它在內核層連通了其他的物理或虛擬網卡,也就是所有容器和本地主機都放到同一個物理網絡。docker還會給我們創建三個網絡:bridge
/host
/none
,網橋bridge模式是在實際項目中常用的,在沒有指定相關網絡的情況下,容器都會連接到默認的bridge網絡。可以通過 --network
參數指定容器連接的網絡。
docker network ls # 查看宿主機中所有的docker網絡
(1)link連接
默認的橋接網絡支持使用端口映射和docker run --link
命令,實現容器間互相通信。該方法已經在官方文檔中標識為不推薦使用。
(2)自定義bridge網絡,實現容器間通信
從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server,使容器可以直接通過“容器名”通信。使用默認的bridge網絡,不能通過DNS server實現通過容器名通信,但是使用自定義bridge網絡可以做到通過容器名互相通信。
0)使用默認的網橋,即啟動容器時,不指定--network
,此時可通過 ip進行ping
,但是不能通過容器名進行ping
進入容器,查看hosts,此時hosts中並沒有其他容器的信息
docker exec -it contian-name bash
cat /etc/hosts
1)創建網橋
docker network create --driver=bridge mybridge
docker network create \
--driver=bridge \
--subnet=172.28.5.0/24 \
--ip-range=172.28.5.0/24 \
--gateway=172.28.5.1 \
mybridge
2)使用自定義網橋啟動容器
通過--network
指定網橋
docker run --name name --network mybridge -p 8001:8000 image_id
3)查看容器網橋
docker network inspect mybridge
如圖,兩個容器mysql-test、django-test都綁在了該網橋
3、容器加入網橋的方式
1)啟動容器時,通過--network
指定網橋
docker run --network
2)啟動容器后,加入網橋
docker run --name my-name # 不指定網橋
docker network connect my_bridge my-name # 通過 docker network connect 為已啟動的容器添加網橋
七、docker化部署流程
-
docker pull mysql:8.0
拉取MySQL的鏡像 -
項目中編寫
Dockerfile
,docker build -t image_name .
制作項目鏡像 -
創建網橋,
docker network create --driver=bridge mybridge
-
啟動容器
docker run -d --name mysql-1 --network mybridge -e MYSQL_ROOT_PASSWORD=123123 -v /home/xx/mysql_data:/var/lib/mysql -p 3307:3306 mysql:8.0
docker run --name django-test --network mybridge -p 8001:8000 django_test:latst
-
進入容器,可修改項目的配置,或者將配置文件通過
-v
掛載到宿主機