###### tags: `Plus` `Docker`
# Docker 學習筆記
```yaml
docker info #版本號
docker image #顯示掛載鏡像
#-a 列出local
#-q 僅列出image id
#--digests 顯示鏡像摘要訊息(sha256)
#--no-trunc 顯示完整鏡像
docker search 鏡像名稱
#-s 顯示評價星數大於該值之鏡像
#--no-trunc 顯示完整鏡像
#--automated 只列出具備Automated Build功能之鏡像
docker pull 下載鏡像
docker rmi 刪除鏡像1 刪除鏡像2 ...
-f 強制刪除
docker rmi -f $(docker images -qa) #刪除全部images
docker run [OPTIONS] 鏡像名稱或ID
#-i 設置容器使用終端溝通(pseudo-tty)
#-t 為容器開啟cmd模式(STDIN)
#--name 為容器命名
#-P 隨機Port
#-d 背景運行下如果無任何進程執行則自動關閉
#Ctrl+P+Q跳出容器終端
docker ps #列出現在運行容器
#-a 查詢之前執行的容器
#-l 查詢最後執行的容器
#-n 查詢最後執行前n個容器
#-q 容器編號
docker start
docker stop
docker kill #強制關閉容器
docker rm #關閉容器
docker logs -ft --tail 10 容器ID
#顯示執行時間log,最後10個訊息
docker logs --since="2016-07-01"
#顯示執行時間log,由2016-07-01到現在之log
docker top 容器ID
#顯示該容器正在process
docker inspect 容器ID
#查看容器DockerFile設定檔
docker attach 容器ID
#進入容器終端
docker exec -t 容器ID 命令...
#讓該容器執行該命令
docker exec -it 容器ID 命令...
#讓該容器執行該命令後並進入終端
docker cp 容器ID:容器檔案路徑 主機檔案路徑
#複製容器內的檔案到主機上
docker cp 主機檔案路徑 容器ID:容器檔案路徑
#複製主機上的檔案到容器內
docker images commit
#上傳成為新的鏡像
docker run -i 容器名稱 /bin/bash
#執行容器後並進入命令/bin/bash(將會覆蓋設定檔CMD的指令)
docker run -it -p 80:8888 --net=host
#容器內的 8888 連接埠,映射到主機上的 80 連接埠,並且使用'host'虛擬網卡
docker run -it -v /主機共享目錄:/容器上的目錄 鏡像名稱--privileged=true
#將主機內目錄與容器內目錄共享
--privileged=true 開啟docker 防火牆權限
docker run -it -v /主機共享目錄:/容器上的目錄:ro 鏡像名稱
#將主機內目錄與容器內目錄共享但限讀
docker run -it --volumes-from 容器名稱
#將新容器繼承舊容器之volume
docker run --rm --volumes-from storage -v $(pwd):/容器上的目錄 容器名稱
#將容器掛載volume於主機現有目錄下,並於容器關閉後刪除該volume
docker build -f 鏡像設定檔目錄 -t 鏡像倉庫目錄
ifconfig #可查看docker0~9網卡區域ip
docker network #查看該機docker虛擬網卡設定
docker container prune #將刪除所有停止的容器,並且應在所有平臺上以相同的方式工作。
docker system prune -a #清理磁碟,刪除關閉的容器、無用的資料卷和網路,以及dangling映象(即無tag的映象)。
```
# 安裝Docker與Docker-compose
### CentOS:
```bash
sudo yum remove docker docker-common container-selinux docker-selinux docker-engine
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo ##添加yum源
sudo yum clean all ##推荐先清空索引,特别是新版本docker需要换成老版本docker的时候
sudo yum makecache fast
yum list docker-ce --showduplicates | sort -r ##查看下自己能安装的版本都有哪些
sudo yum install -y docker-ce-18.09.9-3.el7 ##此处也可以安装指定版本的docker....
sudo yum install docker-ce ##不指定版本,安装最新版本的docker
sudo groupadd docker
sudo gpasswd -a $USER docker #將user加入可執行docker權限
newgrp docker
sudo systemctl restart docker
sudo systemctl enable docker #设置开机启动
docker info ##验证是否安装成功
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
```
### Ubuntu:
```bash
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
wget https://download.docker.com/linux/ubuntu/gpg
sudo apt-key add gpg
rm gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt-get install docker-ce
sudo gpasswd -a ${USER} docker
sudo usermod -aG docker $USER
#需要登出後才能使用
docker version
#docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
```
# 什麼是Dockerfile ?
* 是一個文字檔,由一行一行的指令所組成,用來描述這個映像檔應該長成怎麼樣
* 利用Dockerfile可以建構/客製化出自己獨一無二的映像檔
* 由於Dockerfile中可以清楚的知道映像檔的組成,因此,在安全性上會有所提升
* 因為是純文字檔,所以檔案很小、很容易分享
## Dockerfile 的組成
基本上Dockerfile是由一行一行的指令列所組成,一行指令對Image來說就是一層的資料層(Layer),一個Image就是靠這樣一層一層的資料累加上去,最後才編譯出自己想要的映像檔,就像蓋房子一樣。
常見Dockerfile內容中的指令如下:
## 開頭代表註解
文件中可使用#符號來進行註解。
## FROM
基底映像檔,必需是「第一個」指令行,指定這個映像檔要以哪一個Image為基底來建構,格式為 ==FROM <image>== 或 ==FROM <image>:<tag>==,範例如下:
```dockerfile
FROM ubuntu:15.04 或
FROM ubuntu
```
## MAINTAINER
映像檔維護者,把它想成是作者即可,格式為 ==MAINTAINER <name>== ,範例如下:
```dockerfile
MAINTAINER John 或
MAINTAINER john@myemail.com 或
MAINTAINER John john@myemail.com
```
## LABEL
設定映像檔的Metadata資訊,例如:作者、EMail、映像檔的說明等,格式為:
==LABEL <key>=<value> <key>=<value> <key>=<value> …==
簡單的來說就是以Key、Value來組成,它可以一行一組,也可以把全部合在一行撰寫,若多組合在一行,則每一組設定中間用空白鍵隔開即可,範例如下:
```dockerfile
LABEL description="這是LABEL的範例" version="1.0" owner="靖技場"
```
和MAINTAINER相比,建議使用LABEL來設定會比較方便,另外,如果要查詢LABEL的資訊,則可以下 ``docker inspect`` 來查詢
## RUN
執行指定的指令,每加一個RUN,就會在基底映像層加上一層資料層,以此類推,一層一層的建構起我們最後想要的映像檔,例如我們可以利用RUN來安裝套件,其格式分為二種:
1. ==RUN <command>==:以shell的形式執行,Linux的預設是/bin/sh -c,而Windows上的預設環境則是cmd /S /C
2. `RUN ["executable", "param1", "param2"]`:以exec的形式執行指令,例如Linux上不想用預設的shell執行指令,那麼就可以透過 `RUN ["/bin/bash", "-c", "echo hello"]` 指定想要的shell
shell形式與exec形式有什麼不同呢?官方有提到:
```
Unlike the shell form, the exec form does not invoke a command shell.
This means that normal shell processing does not happen.
For example, RUN [ "echo", "$HOME" ] will not do variable substitution on $HOME
```
意思是說exec執行的方式不會使用command shell,所以執行 `RUN [ "echo", "$HOME" ]` 這樣的指令列, `$HOME` 這個變數是不會被替代(填入值)的,也就是直接輸出「`$HOME`」,但如果你想要有Shell處理的功能,則可以自行指定shell來達成:``RUN [ "sh", "-c", "echo $HOME" ]``
在使用RUN指令時,有以下注意要點:
如果想要執行的指令很長,可以利用\符號來換行,比較容易閱讀
使用exec形式執行時,必需使用JSON array的格式,因此,請使用雙引號
每一個RUN就會新增一層資料層,為了減少不必要的資料層,可以利用&&來串連多個命令
簡單的RUN指令範例如下:
```
# install packages, only for demo
RUN mkdir -p /home/demo/docker
RUN ["apt-get", "install", "python3"]
RUN apt-get update && apt-get install -y --force-yes apache2 \
firefox \
php5
```
## CMD
設定映像檔啟動為Container時預設要執行的指令,其指令共支援三種格式:
1. ==CMD ["executable","param1″,"param2″]== :exec形式,官方推薦此種方式
2. ``CMD ["param1″,"param2"]`` :適用於有定義ENTRYPOINT指令的時候,CMD中的參數會做為ENTRYPOINT的預設參數
3. ``CMD command param1 param2`` :會以shell的形式執行,預設是在「/bin/sh -c」下執行,適合在需要互動的指令時使用CMD的注意事項:
Dockerfile中只能有一行CMD,若有多行CMD,則只有最後一行會生效
若在建立Container時有帶執行的命令,則CMD的指令會被蓋掉,例如:執行 ``docker run <image id>`` 時,CMD所定義的指令會被執行,但當執行 ``docker run <image id> bash`` 時,Container就會執行bash,而原本CMD中定義的值就會覆蓋
CMD範例如下:
```dockerfile
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
CMD [ "sh", "-c", "echo $HOME" ]
#作為ENTRYPOINT的參數使用
CMD ["Hello"]
```
## ENTRYPOINT
和CMD一樣,用來設定映像檔啟動Container時要執行的指令,但不同的是,ENTRYPOINT一定會被執行,而不會有像CMD覆蓋的情況發生,支援二種格式:
``ENTRYPOINT ["executable", "param1", "param2"]``:exec形式,官方推薦此種方式
``ENTRYPOINT command param1 param2:shell`` 的形式
使用ENTRYPOINT的注意事項:
Dockerfile中只能有一行ENTRYPOINT,若有多行ENTRYPOINT,則只有最後一行會生效
若在建立Container時有帶執行的命令,ENTRYPOINT的指令不會被覆蓋,也就是一定會執行
如果想要覆蓋ENTRYPOINT的預設值,則在啟動Container時,可以加上「–entrypoint」的參數,例如:docker run –entrypoint
舉個實例,來看看ENTRYPOINT與CMD的關係,假設Dockerfile中的定義如下:
```
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["World"]
```
如果是使用 ``docker run -it <image>`` 來啟動Container,那麼輸出的結果為「Hello World」,但如果是用 ``docker run -it <image> Docker`` 來啟動,則輸出結果會變成「Hello Docker」,因為CMD的值被覆蓋掉了
## COPY
複製本地端的檔案/目錄到映像檔的指定位置中,其格式為:
* ``COPY [–chown=<user>:<group>] <src>… <dest>``
* ``COPY [–chown=<user>:<group>] ["<src>",… "<dest>"]``
使用COPY的注意事項:
指令的來源位置可以多個
如果目的位置是目錄的話,記得最後要以/結尾,例如:/mypath/
目的位置可以是絕對路徑或者相對於WORKDIR定義值的相對路徑
若目的位置不存在,會自動建立
COPY的範例如下:
* ``COPY file1.txt file2.js file3.json ./``
* ``COPY ["file1.txt", "file2.js", "file3.json" "./"]``
## ADD
和COPY一樣,可將本地端的檔案/目錄加到映像檔的指定位置內,其格式為:
* ``ADD [–chown=<user>:<group>] <src>… <dest>``
* ``ADD [–chown=<user>:<group>] ["<src>",… "<dest>"]``
雖然ADD和CMD功能類似,但有二點最大的不同:
ADD的來源路徑支援URL,也就是說可以加入遠端的檔案,COPY則不支援URL
若來源檔案是壓縮檔(副檔名為gzip、bzip2、xz),
則使用ADD加入檔案時會自動解壓縮,而COPY不會
ADD的範例如下:
```dockerfile
ADD file1.txt file2.js file3.json ./
# ENV_DEMO_VALUE 是用ENV指令所設定的環境變數
ADD https://www.google.com/demo.gzip $ENV_DEMO_VALUE
```
除非你有自動解壓的需求,不然一般建議會使用「COPY」來加入檔案
## EXPOSE
宣告在映像檔中預設要使用(對外)的連接埠,格式如下:
* ``EXPOSE <port> [<port>/<protocol>…]``
EXPOSE預設的協定是TCP,但如果不是要TCP的話,可以自行指定,範例如下:
```dockerfile
EXPOSE 80/tcp
EXPOSE 80/udp
```
使用EXPOSE所定義的連接埠並不會自動的啟用,而只是做提示的作用而已,要將連接埠啟用需要在執行docker run時,搭配-p或-P的參數來啟用。
小寫的-p可以自行指定與主機關聯的連接埠,例如:
```
docker run -p 80:80/tcp -p 80:80/udp demo
```
大寫的-P則會啟用所有EXPOSE所定義的連接埠,並動態(隨機)的關聯到主機的連接埠,例如:EXPOSE 80 可能隨機關聯到主機的 45123 連接埠,其範例如下:
```
docker run -P demo
```
## ENV
設定環境變數,支援二種格式:
1. ``ENV <key> <value>``:Key後面的第一個空白鍵後會視為Value
2. ``ENV <key>=<value> …``:用等於符號來定義,每一組中間以空白鍵隔開,我個人比較喜歡這種形式,不容易搞混
ENV範例如下:
```dockerfile
ENV demoPATH="/var/log" demoVer="1.0"
# 設置「/tmp/test.txt」給demoFile變數
ENV demoFile /tmp/test.txt
# 使用環境變數的例子,有沒有用大括號都可以
COPY debug.log ${demoPATH}
ADD $demoFile /foo
```
使用ENV設置環境變數後,在Dockerfile中其他的指令就可以利用,之後在建起來的Container裡也可以使用該變數
## VOLUME
建立本機或來自其他容器的掛載點,指令格式如下:
* ``VOLUME ["/data"]``
VOLUME的值可以是JSON的Array格式,也可以是純文字,例如下以範例:
```dockerfile
VOLUME ["/var/log/"] 或
VOLUME ["/demo1","/demo2"] 或
VOLUME /var/log 或
VOLUME /var/log /var/db
```
要特別注意的是使用VOLUME來定義掛載點時,是無法指定本機對應的目錄的,對應到哪個目錄是自動產生,我們可以透過docker inspect來查詢目錄資訊
## WORKDIR
設定工作目錄,其格式如下:
* ``WORKDIR /path/to/workdir``
當設定WORKDIR後,Dockerfile中的RUN、CMD、ENTRYPOINT、COPY、ADD等指令就會在該工作目錄下執行,以下是官方的示範:
```dockerfile
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
```
在上面的範例中,`pwd`最後會在 `/a/b/c` 目錄下執行,如果目錄不存在,系統會幫忙自動建立
## USER
指定運行Container時的用戶名稱或UID,其格式如下:
```dockerfile
USER <user>[:<group>]
USER <UID>[:<gid>]
```
在定義了USER後,則Dockerfile中的RUN、CMD、ENTRYPOINT等指令便會以USER指定的用戶來執行,前提條件是該用戶必需是已存在的,否則指定會失敗,範例如下:
```dockerfile
RUN groupadd -r tester && useradd -r -g tester tester
# 指定用戶名稱
USER tester
# 或使用UID來指定
USER 1000
```
## ARG
設定在建置映像檔時可傳入的參數,即定義變數名稱以及變數的預設值,其格式為:
* ``ARG <name>[=<default value>]``
ARG和ENV的功能類似,都可以設定變數,但是ARG設定的值是供建置映像檔時使用(搭配docker build指令),在Container中是無法使用這些變數的,相反地,ENV的值則可以在Container中存取,例如ARG的定義如下:
```dockerfile
ARG Param1
ARG Param2=somevalue
```
建構映像檔案,可利用 ``–build-arg <varname>=<value>`` 來指定參數,例如:
```dockerfile
docker build --build-arg Param1=demo -t myimage:v1 .
```
在上面的例子中,我們在docker build中利用 ``–build-arg <varname>=<value>`` 參數將Param1的值變更為「demo」,而Param2的值並沒有指定,所以保留預設值「somevalue」
## ONBUILD
若這個映像檔是作為其他映像檔的基底時,便需要定義ONBUILD指令,格式為:
* ``ONBUILD [INSTRUCTION]``
ONBUILD後面接的指令在自建的映像檔中不會被執行,只有當這個映像檔是作為其他映像檔的基底時才會被觸發,例如A映像檔的Dockerfile定義如下(假設名稱為A-Image):
```dockerfile
...(以上略)
ONBUILD ADD . /home/tmp
ONBUILD mkdir -p /home/demo/docker
...(以下略)
```
如果B映像檔是以A映像檔為基底,則A映像檔中的ONBUILD指令會被觸發,等於是以下指令:
```dockerfile
# 以A映像檔為基底
FROM A-Image
# 觸發A映像檔ONBUILD的指令,即會自動執行下面二個指令行
# 下面二行指令不用自己加,Docker會自動去執行,這邊寫出只是方便做說明
ADD . /home/tmp
mkdir -p /home/demo/docker
```
# 如何使用Dockerfile ?
介紹了那麼多的指令,最終的目的就是利用Dockerfile來建立我們自己的映像檔,其指令為docker build,範例如下:
```dockerfile
# 在目前目錄尋找Dockerfile或dockerfile
docker build -t myimage:v1 .
```
``-t`` :Name and optionally a tag in the ‘name:tag’ format,指定映像檔名稱、標籤
在上面的範例中,是假設Dockerfile在當前目錄下,因此會以.結尾,若是在不同目錄,則可以直接接Dockerfile所在目錄或用-f來指定Dockerfile位置,例如:
```dockerfile
# 後面接Dockerfile的所在目錄
docker build -t myimage:v2 ./docker
docker build -f /path/to/a/Dockerfile -t myimage:v3 .
```
用 ``-f`` 來指定Dockerfile的位置時,後面接的目錄(及其子目錄)需要能夠找到Dockerfile,否則會出現context錯誤
小結:Dockerfile裡面的指令也不少,但因篇幅的關係這邊沒有列出所有的指令,但應該也足夠滿足大部分的需求,想要更深入研究的話,建議可以參考官方的文件,但我個人認為最快的學習方法可以自己動手做做看,比較能夠體會每個指令到底有什麼功用
### Dockerfile實例
```dockerfile=
FROM centos
ENV WKDIR="/tmp"
WORKDIR $WKDIR
RUN mkdir "中文目錄測試"
## UTF-8雖能正常輸入,但無法正常顯示非lang-en.UTF-8
RUN yum -y install nano
RUN yum -y install net-tools
EXPOSE 80
CMD echo --------------------- Setup Sucessed!
## CMD會在安裝過程中逐步執行等同RUN,但只有最後一行會被docker run 執行
CMD /bin/bash
```
```shell
docker build -f ./dockerfile -t centos_plus:1.0 .
```
```shell
docker run -it centos_plus:1.0
```
# Docker Compose
```yaml
version: '3.8'
services:
# db:
# image: mariadb
# working_dir: #預設工作目錄
# /root/
# environment:
# MYSQL_ROOT_PASSWORD: example
example-01:
image: golang:1.15.13-stretch #鏡像名稱與版本,可參考https://hub.docker.com/layers/golang/library/golang/1.15.13-stretch/images/sha256-3c251a7c830aa6bcf0fe57a71d39dc4ba59d4d65775407d989c7f459da3ac207?context=explore
container_name: go_API #為容器命名
restart: always
volumes: #HOST:CONTAINER:ro
- ./API:/root/:ro #限讀模式
- /dev/shm/API:/dev/shm/ #抓取主機RamDisk
working_dir: #預設工作目錄
/root/
command: #容器內服務啟動指令
>
sh -c "
echo 目錄/dev/shm/:&&
ls -la /dev/shm/ &&
echo 目錄./:&&
ls -la ./
"
#↑批次指令範例
ports: #對外Port:容器內Port
- "8080:8080"
networks:
- default
- outside
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
#limit設置範例
environment:
- TZ=Asia/Taipei
#環境變數設置範例
networks:
outside:
external: true
# version: "3.5": 選定 docker-compose 的版本,每個版本提供的 API 方法有所差異。
# services: 此欄位底下會有所有的容器,以下分別有server與db兩個 容器。
# build: 說明此容器要使用特定 Dockerfile 來 build,context為檔案目錄,dockerfile為 Dockerfile 的名字。
# working_dir: 指定 docker 啟動時所在的目錄,如果目錄不存在會自動創建一個。
# volumes: 將本機檔案掛載至 docker 內部,本機檔案更新時 docker 內部的掛載檔案也會更新。
# ports: 將本機的 port 做 mapping 與 docker 內部的 poart。
# depends_on: 說明 a 容器與 b 容器有相關,會等到 b 容器啟動完畢後,再啟動 a 容器。
# entrypoint: 指定 docker 啟動時的預設指令。
# restart: 當容器不正常關閉時,會重新啟動容器。
# image: 如果不使用 Dockerfile 來建立容器,你可以直接使用 docker image 來啟動容器。
# environment: 指定容器內的環境變數。
```
# Docker Compose - 範例
### Chrome Debug with Boswer Remote
```yaml
version: '3'
services:
alpine-chrome:
image: zenika/alpine-chrome:89
command: [chromium-browser, "--headless", "--disable-gpu", "--no-sandbox","--disable-software-rasterizer", "--remote-debugging-address=0.0.0.0","--shm-size=1gb", "--remote-debugging-port=9090"]
ports:
- "9090:9090"
```
### Code-Server with Golang
```yaml
version: '3.8'
services:
API.code-server:
image: linuxserver/code-server:amd64-version-v3.10.2
container_name: code-server
privileged: true #開啟root權限
volumes:
- ./Code-Server:/config
- ./workspace:/config/workspace
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Taipei #時區
- PASSWORD=qwerty #雲端vscode登入密碼
- HASHED_PASSWORD= #optional
- SUDO_PASSWORD=qwerty #雲端環境sudo密碼
- SUDO_PASSWORD_HASH= #optional
#- PROXY_DOMAIN=code-server.my.domain #optional
- GO111MODULE=on #強制開啟go.mod版控
- GOPATH=/config/DevOpt/go-1.15.13/GoPath #GoPath絕對路徑
- GOROOT=/config/DevOpt/go-1.15.13/GoRoot #GoRoot絕對路徑
- GOTOOLDIR=/config/DevOpt/go-1.15.13/GoRoot/pkg/tool/linux_amd64 #GOTOOLDIR絕對路徑
- PATH=/config/DevOpt/go-1.15.13/GoPath/bin:/config/DevOpt/go-1.15.13/GoRoot/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin #設定go編譯器路徑
ports:
- 8080:8080 #API子程式專用port
- 8081:8443 #code-server外部用port
command: #容器內服務啟動指令
>
sh -c "
echo 目錄./:&&
ls -la ./config &&
echo $PATH &&
code-server --port 18080 --host 0.0.0.0
"
#API子程式專用port必須與code-server port分開
#code-server為啟動雲端IDE的指令
restart: unless-stopped
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
# networks:
# outside:
# external: true
```
### Firefox with VNC
```yaml
version: '3'
services:
firefox:
container_name: Firefox_for_Code-Server
image: ich777/firefox:amd64
ports:
- "9090:8080"
environment:
- FIREFOX_V=latest
- FIREFOX_LANG=zh-TW
- CUSTOM_RES_W=1600 #VNC解析度
- CUSTOM_RES_H=900
- UID=99
- GID=100
- UMASK=000
- DATA_PERM=770
volumes:
- "./appdata:/firefox:rw" #存放firefox目錄
```
### Redis-Server
```yaml
version: '3.8'
services:
# db:
# image: mariadb
# working_dir: #預設工作目錄
# /root/
# environment:
# MYSQL_ROOT_PASSWORD: example
Redis-Server:
restart: always
container_name: redis
image: redis:6.2.4-alpine
ports:
- 16379:6379
volumes:
- ./Redis/data:/data
networks:
outsite:
external: true
```
### VNC-xfce
```yaml
version: '3.8'
services:
ubuntu-xfce-vnc:
container_name: xfce
image: imlala/ubuntu-xfce-vnc-novnc:latest
shm_size: "1gb" # 防止高分辨率下Chromium崩溃
ports:
- 5900:5900
- 9090:6080
environment:
- VNC_PASSWD=qwerty
- GEOMETRY=1600x900
- DEPTH=24
volumes:
- ./Downloads:/root/Downloads
restart: unless-stopped
```
### Hedgedoc(hackmd社群版)
```yaml=
# Using version 3 to provide play-with-docker badge
# You can change to version 2 without breaking.
#version: '2'
version: '3'
services:
database:
# Don't upgrade PostgreSQL by simply changing the version number
# You need to migrate the Database to the new PostgreSQL version
image: postgres:13.4-alpine
#mem_limit: 256mb # version 2 only
#memswap_limit: 512mb # version 2 only
#read_only: true # not supported in swarm mode please enable along with tmpfs
#tmpfs:
# - /run/postgresql:size=512K
# - /tmp:size=256K
environment:
- POSTGRES_USER=dbuser
- POSTGRES_PASSWORD=dbpassword
- POSTGRES_DB=dbName
volumes:
- ./postgresql/data:/var/lib/postgresql/data
networks:
backend:
restart: always
# MySQL example
# Most of the documentation that applies to PostgreSQL applies also to MySQL
#database:
# # You should be able to upgrade MySQL without problems
# # but to make sure no even when a problem appears you
# # should have a backup
# image: mariadb:10
# environment:
# - MYSQL_USER=dbuser
# - MYSQL_PASSWORD=dbpassword
# - MYSQL_DATABASE=dbName
# - MYSQL_ALLOW_EMPTY_PASSWORD=true
# volumes:
# - ./db/data:/var/lib/mysql
# # This config provides UTF-8 support to the database by default
# # If this config is not used, HedgeDoc breaks as it tries to write
# # UTF-8 to a latin database.
# - ./resources/utf8.cnf:/etc/mysql/conf.d/utf8.cnf
# networks:
# backend:
# restart: always
app:
# Uncomment the following section to build the image yourself:
#build:
# context: .
# dockerfile: debian/Dockerfile
# args:
# - "VERSION=master"
# - "HEDGEDOC_REPOSITORY=https://github.com/hedgedoc/hedgedoc.git"
image: quay.io/hedgedoc/hedgedoc:1.9.2
#mem_limit: 256mb # version 2 only
#memswap_limit: 512mb # version 2 only
#read_only: true # not supported in swarm mode, enable along with tmpfs
#tmpfs:
# - /tmp:size=10M
# # Make sure you remove this when you use filesystem as upload type
# - /hedgedoc/public/uploads:size=10M
environment:
# **DB_URL** is formatted like: <databasetype>://<username>:<password>@<hostname>:<port>/<database>
# Other examples are:
# - mysql://hedgedoc:password@database:3306/hedgedoc
# - sqlite:///data/sqlite.db (NOT RECOMMENDED)
# - For details see the official sequelize docs: http://docs.sequelizejs.com/en/v3/
- CMD_DB_URL=postgres://dbuser:dbpassword@database:5432/dbName
# **DOMAIN** is the domain under which HedgeDoc will be available. Just the (sub)domain, no protocol or paths.
# You MUST change this if your instance should be available under another domain than "localhost", otherwise your
# instance may be broken.
# You can define only ONE domain.
- CMD_DOMAIN=localhost
# **PROTOCOL_USESSL** defines if generated links should be HTTPS URLs.
# This variable won't activate encryption on the listen port.
# Set this to true if your reverse proxy exposes your instance via HTTPS.
- CMD_PROTOCOL_USESSL=false
# **HSTS_ENABLE** defines if HSTS headers should be sent. Set this to true if you use HTTPS.
- CMD_HSTS_ENABLE=false
# **URL_ADDPORT** defines if generated links should contain the port.
# Set this to false if your reverse uses the default ports (443 for HTTPS or 80 for HTTP).
- CMD_URL_ADDPORT=true
volumes:
- ./uploads:/hedgedoc/public/uploads
ports:
# Ports that are published to the outside.
# The latter port is the port inside the container. It should always stay on 3000
# If you only specify a port it'll published on all interfaces. If you want to use a
# local reverse proxy, you may want to listen on 127.0.0.1.
# Example:
# - "127.0.0.1:3000:3000"
- "3000:3000"
networks:
backend:
restart: always
depends_on:
- database
# Define networks to allow best isolation
networks:
# Internal network for communication with PostgreSQL/MySQL
backend:
```