- Docker ํ๊ฒ์ ์
- Docker์ ํจ๊ปํ๋ ๊ฐ๋ฐ workflow
- Docker ์ฐ์ต ํ๊ฒฝ
- Dockerfile ์์ฑ
- ~docker-compose.yml~ ์์ฑ
- ๋ฐฐํฌ
๋ค์ ์ค ํ๋ ์ด์ ๊ฒฝํํ ์ฌ๋
๋ค๋ฅธ ์ปดํจํฐ์์ ๋น๋ ์๋ฌ๊ฐ ๋๋ ๊ฒฝ์ฐ
๋น๋ํด์ด ๋ฐ์ ํ๋ฉด์ ๋ง์ด ๋์์ก์ง๋ง ๊ทธ๋๋ ๋ค๋ฅธ OS๋ฌธ์ ๋ผ๋์ง ์ฌ์ ํ ๊ฐ๋์ฉ ์ ํ๋ ์ผ์ด์ค์ด๋ค.
ํด๊ฒฐ๋ฒ
Dockerfile ์ ์ฌ์ฉํ๋ค
DB๋ฅผ ์ฐ๊ฒฐํด์ผ ๋๋๋ฐ ๋ด ์ปดํจํฐ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ
- ์น๊ฐ๋ฐ์ ํ ๋ ํ๋ก๋์ ๊ณผ ๋์ผํ ํ๊ฒฝ์ผ๋ก ์ธํ ํด์ผ ํ์ง๋ง ๊ท์ฐฎ๋ค
- ์ด๋ฏธ ๋ด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ฌ์ฉ์ค์ด๊ฑฐ๋ ํน์ ๊ท์ฐฎ๋ค
- ํฌ๋กค๋ง์ ํ๋ฉด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ณ ์ถ์๋ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ ํ๊ธฐ๊ฐ ๊ท์ฐฎ๋ค
ํด๊ฒฐ๋ฒ
docker-compose๋ก ํด๊ฒฐํ๋ค.
๋ฐฐํฌ ๋๋ฌด ๊ท์ฐฎ๋ค..
๋ฐฐํฌ ํ๊ฒฝ์์ ํ๊ฒฝ์ค์ ๋ฑ ์ฌ๋ฌ๊ฐ์ง๋ก ์ค์ ์ ์ก์ ์ฃผ๊ธฐ ๊ท์ฐฎ์ ์ํฉ๋ docker๋ก ํด๊ฒฐ ํ ์ ์๋ค.
ํด๊ฒฐ๋ฒ
docker stack deploy ๋ฅผ ์ฌ์ฉํ๋ค
์๋น์ค scalability๋ ์ฝ๊ฒ ํ์ผ๋ฉด ์ข๊ฒ ๋ค..
ํด๊ฒฐ๋ฒ
docker service scale frontend=10 ํ์ค์ด๋ฉด ๋๋ค.
Docker๋ก ๊ฐ๋ฐํ๋ฉด ์๋์ ๊ฐ์ ํ๋ก์ธ์ค๋ก ๊ฐ๋ฐ์ ํ๊ฒ ๋๋ค
Dockerfile์์ฑdocker-compose.yml์์ฑ- ๊ฐ๋ฐ
docker-compose up
- ๋ฐฐํฌ
- ์ด๋ฏธ์งํ ๋ฐ
registry docker stack deploy
- ์ด๋ฏธ์งํ ๋ฐ
http://labs.play-with-docker.com/
Dockerfile์ docker image๋ฅผ ์์ฑํ๋ ๊ฐ๋จํ ์คํฌ๋ฆฝํธ์ด๋คDockerfile๋ก image๊ฐ ๋ง๋ค์ด์ง๋ฉด container๋ก ์คํ์ด ๊ฐ๋ฅํ๊ฒ ๋๋ค.- Virtualbox๋ก ์น๋ฉด
- image = isoํ์ผ
- container = ์ค์ ์คํ๋๋ ๊ฐ์ํ๊ฒฝ
- ๋ฌผ๋ก docker๋ virtualization์ด ์๋๋ผ ํธ์คํธ์ ์ปค๋์ ์ฌ์ฉํด์ ์ฌ์ค์ Native Application์ด๋ค.
์์๋ก ์๋์ ๊ฐ์ Flask App์ด ์๋ค.
from flask import Flask, render_template
import random
app = Flask(__name__)
# list of cat images
images = [
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26388-1381844103-11.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr01/15/9/anigif_enhanced-buzz-31540-1381844535-8.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26390-1381844163-18.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-1376-1381846217-0.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3391-1381844336-26.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/10/anigif_enhanced-buzz-29111-1381845968-0.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/9/anigif_enhanced-buzz-3409-1381844582-13.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr02/15/9/anigif_enhanced-buzz-19667-1381844937-10.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26358-1381845043-13.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-18774-1381844645-6.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr06/15/9/anigif_enhanced-buzz-25158-1381844793-0.gif",
"http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr03/15/10/anigif_enhanced-buzz-11980-1381846269-1.gif"
]
@app.route('/')
def index():
url = random.choice(images)
return render_template('index.html', url=url)
if __name__ == "__main__":
app.run(host="0.0.0.0")ํ๋ก์ ํธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
.
โโโ app.py
โโโ requirements.txt
โโโ templates
โโโ index.html
์ ํ๋ก์ ํธ๋ก Dockerfile ์ ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
# FROM: ๋ฒ ์ด์ค ์ด๋ฏธ์ง๋ฅผ ์ ํด์ค๋ค.
FROM python:3-alpine
# requirements.txt ํ์ผ ๋ณต์ฌ
COPY requirements.txt /code/
RUN pip install --no-cache-dir -r /code/requirements.txt
# app.py์ index.html ๋ณต์ฌ
COPY app.py /code/
COPY templates/index.html /code/templates/
EXPOSE 5000
WORKDIR /code
CMD ["python", "app.py"]์ธ์ธ ํ์๋ ์๊ณ ํ์ํ ๋๋ง๋ค Dockerfile Reference ์์ ์ฐพ์๋ณด๋ฉด ๋๋ค
๋ช๊ฐ์ง ํฌ์ธํธ๋
FROM- ๋ฒ ์ด์ค ์ด๋ฏธ์ง๋ฅผ ์ ํด์ค๋ค. ์๋ก ๋ง๋๋ ๊ฒ๋ณด๋ค official image ์๋ฅผ ์ด์ฉํ๋๊ฒ ์ข๊ณ alpine์ ๋ฆฌ๋ ์ค ์ข ๋ฅ ์ค ํ๋์ธ๋ฐ ์ฉ๋์ด 5mb์ ๋ถ๊ณผํด ๋๋ถ๋ถ ๋ชจ๋ ๊ณต์ ์ด๋ฏธ์ง๋ค์ด alpine์ ์ง์ํ๋ค.
EXPOSE- ํฌํธ 5000์ ์ด๊ฒ ๋ค๋ ์๋ฆฌ์ด์ง๋ง ์ค์ ๋ก ์๋ฌด ์ผ๋ ํ์ง ์๋๋ค. ์ฌ์ฉ์์๊ฒ ํฌํธ 5000๋ฒ์์ ์ด ์ดํ๋ฆฌ์ผ์ด์
์ด ๋์๊ฐ๋ค๊ณ ์๋ ค์ฃผ๋ ์ฉ๋์ด๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ํฌํธ ๋ช๋ฒ์ ์ฐ๊ฒฐํด์ค์ผ ๋๋์ง ํท๊ฐ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค. ์ค์ ๋ก๋
ENVํน์ARG๋ก ์ค์ ํด์ค๋ค.
์ด์ ์ด๊ฑธ ์ด๋ฏธ์ง๋ก ๋น๋ํ๋ค
docker build -t my_flask_app .Sending build context to Docker daemon 7.68kB Step 1/8 : FROM python:3-alpine ---> d26cf7d4701d Step 2/8 : COPY requirements.txt /code/ ---> Using cache ---> 459e0df94893 Step 3/8 : RUN pip install --no-cache-dir -r /code/requirements.txt ---> Using cache ---> 5a618308e9b8 Step 4/8 : COPY app.py /code/ ---> Using cache ---> e35197a2ee91 Step 5/8 : COPY templates/index.html /code/templates/ ---> Using cache ---> 734c689d69e3 Step 6/8 : EXPOSE 5000 ---> Using cache ---> 0c4d7984da84 Step 7/8 : WORKDIR /code ---> Using cache ---> 89bfc8e45446 Step 8/8 : CMD python app.py ---> Using cache ---> 51fb98413e28 Successfully built 51fb98413e28 Successfully tagged my_flask_app:latest
๋น๋๊ฐ ๋์๋์ง ํ์ธ์ ํ๋ค
docker image lsREPOSITORY TAG IMAGE ID CREATED SIZE my_flask_app latest 51fb98413e28 20 seconds ago 98.7MB
image๋ฅผ container๋ก ์คํ์ ๋ค์๊ณผ ๊ฐ๋ค.
docker container run --name flask --publish 8080:5000 -d my_flask_appfee755b1f3b34bff0b8d8f676a696976cfe4b24b9555b7257428c56ab799424d
๊ตฌ) ์ปค๋งจ๋์ธ docker run ์ผ๋ก ํด๋ ๋์ง๋ง ์ ๋ช
๋ น์ด๋ docker <<context>> <<command>> ํํ๋ฅผ ์ฌ์ฉํ๋ค.
์ฆ ์ฌ๊ธฐ์๋ docker container run ์ธ ๊ฒ์ด๋ค. ์ปค๋งจ๋๋ ๋งค๋ฒ --help ๋ฅผ ๋ณด๋ฉด ๋๋ค.
docker container --helpUsage: docker container COMMAND
Manage containers
Options:
--help Print usage
Commands:
attach Attach local standard input, output, and error streams to a running container
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
exec Run a command in a running container
export Export a container's filesystem as a tar archive
inspect Display detailed information on one or more containers
kill Kill one or more running containers
logs Fetch the logs of a container
ls List containers
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
prune Remove all stopped containers
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
run Run a command in a new container
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
wait Block until one or more containers stop, then print their exit codes
Run 'docker container COMMAND --help' for more information on a command.
์ด์จ๋ docker container run ์ดํ container id๊ฐ ๋ฐํ๋์์ผ๋ฉด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋ ๊ฒ์ด๋ค.
ํ์ธ์ ํ๋ฉด ๋์์ค์ธ๊ฒ์ ์ ์ ์๋ค.
GET 127.0.0.1:8080HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 732
Server: Werkzeug/0.12.2 Python/3.6.3
Date: Sat, 07 Oct 2017 08:19:33 GMT
<html>
<head>
<style type="text/css">
body {
background: black;
color: white;
}
div.container {
max-width: 500px;
margin: 100px auto;
border: 20px solid white;
padding: 10px;
text-align: center;
}
h4 {
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="container">
<h4>Cat Gif of the day</h4>
<img src="http://ak-hdl.buzzfed.com/static/2013-10/enhanced/webdr05/15/9/anigif_enhanced-buzz-26358-1381845043-13.gif" />
<p><small>Courtesy: <a href="http://www.buzzfeed.com/copyranter/the-best-cat-gif-post-in-the-history-of-cat-gifs">Buzzfeed</a></small></p>
</div>
</body>
</html>
์๋์ ๊ฐ์ด ์คํ์ค์ธ ์ปจํ ์ด๋๋ฅผ ํ์ธํ ์ ์๋ค.
docker container ls -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fee755b1f3b3 my_flask_app "python app.py" 27 minutes ago Up 27 minutes 0.0.0.0:8080->5000/tcp flask
๊ท์ฐฎ์ผ๋ force๋ก ์ง์ด๋ค
docker container rm -f flask์์ด์ก๋ค.
docker container ls -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
์ค์ ๋ก docker๋ฅผ ์ฌ์ฉํ ๋๋ ํ๋ก์ ํธ๋ฅผ ์์ํ๊ธฐ์ ์ Dockerfile ๊ณผ docker-compose.yml ๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋๊ณ ์์์ ํ๋ค.
์ด์ ๋ถํฐ๋ ํ์ ํ DevOps ๋ผ๊ณ ๊ฐ์ ํ๊ณ ๋ค์๊ณผ ๊ฐ์ ์ผ์ ํด์ผ ํ๋ค๊ณ ๊ฐ์ ํ๋ค.
- drupal 8.2 ๋ฒ์ ์ ์ค์นํ๋ค
- drupal bootstrap theme์ ์ค์นํ๋ค
- port๋ 8080์ ์ด์ฉํ๋ค.
- database๋ postgres 9.6 ๋ฒ์ ์ ์ฌ์ฉํ๋ค
- postgres password๋ qwer1234qwer ๋ก ํ๋ค
- ๋ฐ์ดํฐ๋ container๊ฐ ๋ ์๊ฐ๋ ๋ณด์กดํ๋๋ก ํ๋ค
์ฐ์ ๊ฐ์ฅ ๋จผ์ ํ ์ผ์ Dockerfile ์ ๋ง๋๋ ์ผ์ด๋ค. ์ด ๊ฒฝ์ฐ๋ ์์ด๋ ๋๊ธด ํ์ง๋ง ๊ทธ๋ฅ ํ๋ค.
FROM drupal:8.2
RUN apt-get update \
&& apt-get install -y git \
&& rm -rf /var/lib/apt/lists*
WORKDIR /var/www/html/themes
RUN git clone --branch 8.x-3.x --single-branch --depth 1 https://git.drupal.org/project/bootstrap.git \
&& chown -R www-data:www-data bootstrap
WORKDIR /var/www/html/var/www/html ์ด๋ ์ด๋ฐ๊ฑด ์ด๋ป๊ฒ ์์ ์๋๊ฐ? Dockerhub/drupal ์์ ์ฌ๋ ค๋์ README ๋ฅผ ๋ณด๋ฉด ๋๋ค.
docker-compose.yml ์ ๋ค์๊ณผ ๊ฐ๋ค.
version: "3"
services:
drupal:
build: .
image: custom-drupal
depends_on:
- db
ports:
- 8080:80
volumes:
- drupal-modules:/var/www/html/modules
- drupal-profiles:/var/www/html/profiles
- drupal-sites:/var/www/html/sites
- drupal-themes:/var/www/html/themes
db:
image: postgres:9.6
environment:
POSTGRES_PASSWORD: qwer1234qwer
volumes:
- drupal-data:/var/lib/postgresql/data
volumes:
drupal-data:
drupal-modules:
drupal-profiles:
drupal-sites:
drupal-themes:yamlํฌ๋งท์ ์ฌ์ฉํ๋ค.- volumes์ ์ค์ ํธ์คํธ์ ๋ณผ๋ฅจ์ ์ฌ์ฉํด ์ฝํ
์ด๋๊ฐ ์์ด์ง๋๋ผ๋ ๋ฐ์ดํฐ๊ฐ ๋จ์์๊ฒ ๋๋ค.
- ์๋ฌด๊ฒ๋ ์์ฑํ์ง ์์ผ๋ฉด
docker volume์ ์ฌ์ฉํ๋ค.
- ์๋ฌด๊ฒ๋ ์์ฑํ์ง ์์ผ๋ฉด
environment๋ฅผ ํตํด ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ํ ์ ์๋ค.- ์ด๋ฐ secret๋ค์ ํ๊ฒฝ๋ณ์๋ก ์ค์ ํ๋๊ฑด ์ข์ง ์๋ค.
- ์ค์ ๋ก๋
docker secret์ ์ฌ์ฉํ๋ค.
์์ธํ ํค์๋๋ Docker Compose Reference ์์ ํ์ธํ๋ค.
์ด์ ์คํ์ docker-compose up ์ ์ฌ์ฉํ๋ค.
๋จผ์ help๋ฅผ ์ดํด๋ณธ๋ค.
docker-compose --helpDefine and run multi-container applications with Docker.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
--verbose Show more output
--no-ansi Do not print ANSI control characters
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the name specified
in the client certificate (for example if your docker host
is an IP address)
--project-directory PATH Specify an alternate working directory
(default: the path of the Compose file)
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
์ด์ ์คํ์ ํ๋ค.
docker-compose up -ddocker container ls -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d448b78b4fd custom-drupal "docker-php-entryp..." 19 seconds ago Up 18 seconds 0.0.0.0:8080->80/tcp drupal_drupal_1 4f2cf2a1722f postgres:9.6 "docker-entrypoint..." 19 seconds ago Up 18 seconds 5432/tcp drupal_db_1
์ด์ ๋ก์ปฌํธ์คํธ:8080์ผ๋ก ๊ฐ๋ณด๋ฉด
GET 127.0.0.1:8080HTTP/1.1 302 Found
Date: Sat, 07 Oct 2017 09:04:22 GMT
Server: Apache/2.4.10 (Debian)
X-Powered-By: PHP/7.1.5
Cache-Control: no-cache
Location: /core/install.php
Content-Length: 312
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="1;url=/core/install.php" />
<title>Redirecting to /core/install.php</title>
</head>
<body>
Redirecting to <a href="/core/install.php">/core/install.php</a>.
</body>
</html>
drupal ์ค์น๋ก ์ฐ๊ฒฐ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ค์ํ ์ ์ db๋ฅผ ์ ํํ๋ ์์ ์
- postgreSQL ์ ํ
- DATABASE HOST๋
docker-compose.yml์์ ์ง์ ํด์ค ์ด๋ฆ์ธhttp://db์ด๋ค - USERNAME์ ๊ฑด๋๋ฆฌ์ง ์์๊ธฐ ๋๋ฌธ์ postgres ๊ธฐ๋ณธ๊ฐ์ธ
postgres์ด๋ค - PASSWORD๋
qwer1234qwer์ด๋ค
์ค์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ architecture๋ฅผ ๋ฐฐํฌํด์ผ ๋๋ ์ผ์ธ ๊ฒฝ์ฐ,
docker-compose.yml ์ ์๋์ ๊ฐ๋ค.
version: "3"
services:
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
ports:
- 80:80
networks:
- frontend
redis:
image: redis:3.2
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
networks:
- frontend
worker:
image: dockersamples/examplevotingapp_worker
deploy:
placement:
constraints: [node.role == manager]
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
networks:
- frontend
- backend
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
networks:
- backend
result:
image: dockersamples/examplevotingapp_result:before
ports:
- 5001:80
networks:
- backend
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
depends_on:
- db
visualizer:
image: dockersamples/visualizer:stable
ports:
- 8080:8080
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:networks:
frontend:
backend:์ด ๋ถ๋ถ์ docker network ๋ก ๋คํธ์ํฌ๊ฐ ์ ์ ๋ก ์์ฑ ๋ํ ๊ฐ๊ฐ์ ์ฝํ
์ด๋๊ฐ ์ํ๋ ์ค๋ฒ๋ ์ด์์๋ง ์๋ก ํต์ ์ด ๊ฐ๋ฅํ๋ค.
docker network create --driver overlay frontend
docker network create --driver overlay backend์ค์ ๋ฐฐํฌ๋ฅผ ํ ๋๋ docker swarm ์ ์ด์ฉํด ์ฌ๋ฌ๋์ ๋
ธ๋๋ก ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ๋ค์
docker stack deploy -c docker-compose.yml voteapp์ด์ docker-compose.yml ์์ deploy ์ ๋ค์ด๊ฐ ์ต์
๋ค์ด docker stack deploy ๋ฅผ ํ ๋ ์ ์ฉ๋๋ ์ต์
๋ค์ธ ๊ฒ์ด๋ค.
๊ฒฐ๋ก ์
docker-compose๋ development ํ ๋ ์ฌ์ฉํ๋ ๋ช ๋ น์ดdocker stack deploy๋ ์ค์ ๋ฐฐํฌํ ๋ ์ฌ์ฉ ๋๋ ๋ช ๋ น์ดdocker stack deploy๋ฅผ ํ ๊ฒฝ์ฐ Dockerfile๋ก ๋น๋๋ฅผ ๋ชปํ๋ค- ๋ฐฐํฌ ์ด์ ์ ๋ด ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค์ด
registry๋ก ๋ชจ๋ ๋ ธ๋์ ์ ์ํ ์ ์๊ฒ ํด์ค๋ค.
- ๋ฐฐํฌ ์ด์ ์ ๋ด ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค์ด
registry๋ ๋ก์ปฌ ์ ์ฉ dockerhub ๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค. ์ค์ ํด๋ฌ์คํฐ์ ์๋์ผ๋ก ๊ณต์ ๊ฐ ๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค.
docker service create --name registry -p 5000:5000 registry
docker tag my_app 127.0.0.1:5000/my_app
docker push 127.0.0.1:5000/my_app์ด์ ๋ชจ๋ ๋ ธ๋์์ ๋ค์๊ณผ ๊ฐ์ด ๋ด ์ด๋ฏธ์ง๋ฅผ ๋ค์ด ๋ฐ์ ์ ์๋ค.
docker service create --name my_app 127.0.0.1:5000/my_appdocker secret create psql_user psql_user.txtํน์
echo "postgresuser" | docker secret create psql_user -๋ก ์์ฑํ๋ค. (๋์ - ๊ฐ ์ค์ํ๋ค)
์ค์ ์ปจํ
์ด๋์์๋ /run/secrets/psql_user ๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค. ํ์ผ์ฒ๋ผ ๋ณด์ด์ง๋ง ํ์ผ์ด ์๋๋ผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋์ด์๋ค.
services:
psql:
image: postgres
environment:
POSTGRES_USER_FILE: /run/secrets/psql_user
POSTGRES_PASSWORD_FILE: /run/secrets/psql_pass
secrets:
- psql_user
- psql_pass
secrets:
psql_user:
file: ./psql_user.txt
psql_pass:
file: ./psql_pass.txt์ผ๋ก ์ฌ์ฉํ๋ค. ํ์ง๋ง ๋ณด์ ์ด์๋ก ํ์ผ๋ก ์ ์ฅํ๊ธฐ๋ณด๋ค external: true ์ธํ
์ ํ ํ docker secret create ์ผ๋ก ์์ฑํ๋ค.
secrets:
psql_user:
external: true
psql_pass:
external: true๋ค์๊ณผ ๊ฐ์ ํ์ผ๋ก ๊ด๋ฆฌ๋ฅผ ํ๋ค.
- docker-compose.yml
- ์ด๋ฏธ์ง๋ง ์ค์ ๋์ด์๋ ๋ฒ ์ด์ค ํ์ผ
- docker-compose.override.yml
- ๊ฐ๋ฐ์ ์ฌ์ฉ๋๋ config
- docker-compose.prod.yml
- ์ค์ ๋ฐฐํฌ์ ์ฌ์ฉ๋๋ config
- docker-compose.test.yml
- CI์์ ์ฌ์ฉ๋๋ config
docker-compose.yml
version: '3.1'
services:
drupal:
image: drupal:latest
postgres:
image: postgres:9.6docker-compose.override.yml
version: '3.1'
services:
drupal:
build: .
ports:
- "8080:80"
volumes:
- drupal-modules:/var/www/html/modules
- drupal-profiles:/var/www/html/profiles
- drupal-sites:/var/www/html/sites
- ./themes:/var/www/html/themes
postgres:
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/psql-pw
secrets:
- psql-pw
volumes:
- drupal-data:/var/lib/postgresql/data
volumes:
drupal-data:
drupal-modules:
drupal-profiles:
drupal-sites:
drupal-themes:
secrets:
psql-pw:
file: psql-fake-password.txtdocker-compose.prod.yml
version: '3.1'
services:
drupal:
ports:
- "80:80"
volumes:
- drupal-modules:/var/www/html/modules
- drupal-profiles:/var/www/html/profiles
- drupal-sites:/var/www/html/sites
- drupal-themes:/var/www/html/themes
postgres:
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/psql-pw
secrets:
- psql-pw
volumes:
- drupal-data:/var/lib/postgresql/data
volumes:
drupal-data:
drupal-modules:
drupal-profiles:
drupal-sites:
drupal-themes:
secrets:
psql-pw:
external: truedocker-compose.test.yml
version: '3.1'
services:
drupal:
image: drupal
build: .
ports:
- "80:80"
postgres:
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/psql-pw
secrets:
- psql-pw
volumes:
- ./sample-data:/var/lib/postgresql/data
secrets:
psql-pw:
file: psql-fake-password.txt# if you're doing anything beyond your local machine, please pin this to a specific version at https://hub.docker.com/_/node/
FROM node:6
RUN mkdir -p /opt/app
# set our node environment, either development or production
# defaults to production, compose overrides this to development on build and run
ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV
# default to port 80 for node, and 5858 or 9229 for debug
ARG PORT=80
ENV PORT $PORT
EXPOSE $PORT 5858 9229
# check every 30s to ensure this service returns HTTP 200
HEALTHCHECK CMD curl -fs http://localhost:$PORT/healthz || exit 1
# install dependencies first, in a different location for easier app bind mounting for local development
WORKDIR /opt
COPY package.json /opt
RUN npm install && npm cache clean --force
ENV PATH /opt/node_modules/.bin:$PATH
# copy in our source code last, as it changes the most
WORKDIR /opt/app
COPY . /opt/app
# if you want to use npm start instead, then use `docker run --init in production`
# so that signals are passed properly. Note the code in index.js is needed to catch Docker signals
# using node here is still more graceful stopping then npm with --init afaik
# I still can't come up with a good production way to run with npm and graceful shutdown
CMD [ "node", "index.js" ]FROM ubuntu:latest
# Elixir requires UTF-8
RUN apt-get update && apt-get upgrade -y && apt-get install locales && locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
# update and install software
RUN apt-get install -y curl wget git make sudo \
# download and install Erlang apt repo package
&& wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb \
&& dpkg -i erlang-solutions_1.0_all.deb \
&& apt-get update \
&& rm erlang-solutions_1.0_all.deb \
# For some reason, installing Elixir tries to remove this file
# and if it doesn't exist, Elixir won't install. So, we create it.
# Thanks Daniel Berkompas for this tip.
# http://blog.danielberkompas.com
&& touch /etc/init.d/couchdb \
# install latest elixir package
&& apt-get install -y elixir erlang-dev erlang-dialyzer erlang-parsetools \
# clean up after ourselves
&& apt-get clean
# install the Phoenix Mix archive
RUN mix archive.install --force https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez
RUN mix local.hex --force \
&& mix local.rebar --force
# install Node.js (>= 8.0.0) and NPM in order to satisfy brunch.io dependencies
# See http://www.phoenixframework.org/docs/installation#section-node-js-5-0-0-
RUN curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - && sudo apt-get install -y nodejs
WORKDIR /code
COPY . /code
RUN mix deps.get && npm install && npm cache clean --force
EXPOSE 80 4000 4001