✔️ 컨테이너 환경 변수
docker run -e A=100 ubuntu
docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd -e MYSQL_DATABASE=wordpress mysql:5.7
일부 이미지는 실행시 환경 변수가 필요하다.
vagrant@docker ~ docker run -it -e A=100 ubuntu
root@26ea4feac856:/# env
HOSTNAME=26ea4feac856
PWD=/
A=100
HOME=/root
------------------------- 이후 생략 -------------------------
환경 변수 중 하나인 PATH 변수는 이미지 내에 지정되어 있는 것이다. 이미지를 만들 때 환경 변수를 지정할 수 있다.
환경 변수를 제공한다는 것은 어떤 목적이 있을까?
환경 변수(shell의 변수)라고 하는 것은 운영체제나 어플리케이션의 작동에 영향을 미치게 된다.
vagrant@docker ~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
453f47a385aa mysql:5.7 "docker-entrypoint.s…" 15 seconds ago Exited (1) 12 seconds ago priceless_engelbart
26ea4feac856 ubuntu "bash" 5 minutes ago Exited (0) 47 seconds ago epic_greider
9ac154424de0 httpd "httpd-foreground" 15 minutes ago Exited (0) 13 minutes ago priceless_cartwright
14be11b50281 httpd "httpd-foreground" 24 minutes ago Up 24 minutes 80/tcp funny_kare
vagrant@docker ~ docker logs 45
2022-05-04 06:38:48+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.38-1debian10 started.
2022-05-04 06:38:48+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-05-04 06:38:49+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.38-1debian10 started.
2022-05-04 06:38:49+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
데이터베이스 설정 파일 ex) wp-config.php의 그 입력 정보가 내부적으로는 환경 변수로 제공되며 그 환경 변수를 읽어서 DB를 세팅한다. 그래야만 해당하는 정보로 접속을 할 수 있는 것이다.
Dockerhub에는 해당 이미지에 적절한 환경 변수가 필요하다면 환경 변수에 대한 설명이 나와있다.
설명을 잘 읽어보고 환경 변수를 적절히 제공해야 한다.
2022-05-04 06:38:49+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
mysql 이미지를 컨테이너로 생성하기 위해서는 세가지 옵션 중에 하나를 반드시 제공해야만 한다.
이 작업이 되지 않으면 더 이상 컨테이너를 띄우고 app을 실행할 수 없는 것이다.
이런식으로 특정 환경 변수를 요구하는 이미지들이 많이 존재한다.
vagrant@docker ~ docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd mysql:5.7
48e46fa0406a0b066eab7cbe46fa739b6981a0742111a32da74fd9978d7dbd46
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48e46fa0406a mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 3306/tcp, 33060/tcp lucid_meninsky
14be11b50281 httpd "httpd-foreground" 30 minutes ago Up 30 minutes 80/tcp funny_kare
vagrant@docker ~ docker logs 48
------ 이전 쭉 생략 ------
Version: '5.7.38' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
vagrant@docker ~ docker exec -it 48 bash
root@48e46fa0406a:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
MYSQL_ROOT_PASSWORD=P@ssw0rd
이렇게 환경 변수를 제공하면 mysql 데이터베이스에 로그인할 수 있다.
vagrant@docker ~ docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd -e MYSQL_DATABASE=wordpress mysql:5.7
e1873d2bd0a7a07bcd2ec8cc11df39c318c33998a2d7ae1abfe08ebbb62b2fae
vagrant@docker ~ docker exec -it e1 mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| wordpress |
+--------------------+
5 rows in set (0.00 sec)
mysql>
✔️ 컨테이너 정보 확인
docker inspect <CONTAINER>
컨테이너 IP 확인
docker inspect 16a -f '{{ .NetworkSettings.IPAddress }}'
해당 문법은 GO template을 따른다.
"NetworkSettings": {
"IPAddress": "172.17.0.5",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:05",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "f23762de12f4a4546f159773d9c3f6b2dc7682898d8533aaca4ba399bb36d710",
"EndpointID": "43149ea76ca02dd83beec180536eadd4b50255fb6f98ff6be58e70cfab8560a9",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.5",
vagrant@docker ~ docker inspect 56 -f '{{ .NetworkSettings.IPAddress }}'
172.17.0.5
컨테이너는 프로세스지만 고유한 네트워크와 ip를 가진다.
이 ip로 컨테이너와 컨테이너 간의 통신이 가능하다.
vagrant@docker ~ docker inspect b1 -f '{{ .NetworkSettings.IPAddress }}'
172.17.0.3
✔️ 컨테이너 Discovery
vagrant@docker ~ docker run -it mysql:5.7 mysql -h 172.17.0.3 -u root -p
Enter password:
여기서 알 수 있는 것은 컨테이너마다 고유한 ip가 부여되며 서로 해당 ip를 이용해 통신할 수 있다는 것이다.
기본적으로 방화벽이 올라와 있지 않다.
vagrant@docker ~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
vagrant@docker ~ docker run -it mysql:5.7 bash
root@b762e64b63b3:/# %
vagrant@docker ~ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b762e64b63b3 mysql:5.7 "docker-entrypoint.s…" 9 seconds ago Up 8 seconds 3306/tcp, 33060/tcp focused_keldysh
vagrant@docker ~ docker inspect b7 -f '{{ .NetworkSettings.IPAddress }}'
172.17.0.2
DB를 inspect로 ip를 매번 확인해야 한다.
만약 wordpress가 있다면 세팅 전에 ip를 매번 확인해야하는데 이러한 작업을 discovery라고 한다.
어떤 특정 클라이언트가 서버를 찾는 것을 디스커버리 라고 한다.
디스커버리가 유연해야 사용하기가 편한데
vagrant@docker ~ docker run -it --link focused_keldysh mysql:5.7 bash
root@9e858ffe840b:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 focused_keldysh b762e64b63b3
172.17.0.3 9e858ffe840b
/etc/hosts 파일을 보면 자동으로 등록되어 있다.
내가 연결하고자 하는 컨테이너의 이름을 지정하면 /etc/hosts에 등록이 된다.
root@9e858ffe840b:/# mysql -h focused_keldysh -u root -p;
Enter password:
등록된 이후에는 이렇게 이름을 통해 편리하게 접속이 가능하다.
사실 Discovery 작업은 매우 귀찮은 일이다.
나의 상대방의 ip가 무엇인지 알 필요 없이 이름이 있다면 그 이름만 지정해주면 된다.
내부에서는 그 이름을 가지고 접속할 수 있다.
vagrant@docker ~ docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd -e MYSQL_DATABASE=wordpress --name mysqldb mysql:5.7
41beccf734d56903f998ad3ae53cc7e8fab558f2629f8093b6ae9ea72ab1c22f
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
41beccf734d5 mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 3306/tcp, 33060/tcp mysqldb
vagrant@docker ~ docker run -it --link mysqldb mysql:5.7 mysql -h mysqldb -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
이름이라는 것은 우리가 미리 예측 가능하다. 여기서 예측이 가능하다는 것은 미리 지정할 수 있다는 뜻이다.
그리고 실제 클라이언트 입장이 되는 시스템을 만들 때 지정하면 된다. 그 이름을 접속할 때 사용할 수 있다.
여기서 좀 더 응용해서
vagrant@docker ~ docker run -it --link mysqldb:db mysql:5.7 mysql -h db -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.38 MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
별칭을 사용한다.
실제로 원리를 살펴보면 이렇다.
vagrant@docker ~ docker run -it --link mysqldb:db mysql:5.7 bash
root@62ff844d13ef:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 db 41beccf734d5 mysqldb
172.17.0.3 62ff844d13ef
172.17.0.2
는 도커가 알아서 가져오며 우리가 상관하지 않아도 된다.
우리는 db
라는 이름으로 통신할 수 있다. 내부적으로 디스커버리 할 때 아주 쉽게 작업 가능하다.
중요한 점은 link 옵션 사용시 연결하려는 컨테이너는 모두 run 상태여야 한다.
✔️ 컨테이너의 포트를 호스트의 포트로 포워딩 (포트 포워딩)
docker run -p <HOST>:<CONTAINER> <IMAGE>
docker run -d -p 80:80 httpd
vagrant@docker ~ docker run -d httpd
3854969f4e4d191a5a4b78c5c9cd2e0083b99d506a7490ef3c63383b9b40fdf4
여기서 중요한 것은 이 컨테이너는 80번 포트가 열려 있다는 것이다.
이 ubuntu 컴퓨터의 명령어로 여기에 접속할 수는 있으나,
인터넷에 연결되어 있는 시스템에서 해당 ip와 port로 클라이언트가 접속하려면 할 수 있는가?
기본적으로 안된다.
private ip이기 때문에 찾아올 수 없다.
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3854969f4e4d httpd "httpd-foreground" About a minute ago Up About a minute 80/tcp sharp_banach
vagrant@docker ~ docker inspect 38 -f '{{ .NetworkSettings.IPAddress }}'
172.17.0.2
vagrant@docker ~ curl 172.17.0.2
<html><body><h1>It works!</h1></body></html>
VM에서는 해당 ip로 curl 명령을 실행하면 내용이 잘 뜨는 것을 확인할 수 있지만
당연하게도 윈도우에서 접속하면 접속이 불가능하다.
publish
: 컨테이너 포트를 호스트에 노출시키는 것, 포트를 포워딩한다.
도커 호스트가 있고 ip를 가진 httpd 컨테이너가 80번 포트를 열고 있다.
호스트 내에서 명령어를 치고는 들어갈 수 있으나 외부에서는 불가능하다.
포트를 도커 호스트에 있는 포트로 연결 시켜준다. 그러면 이 포트로 접속하면 내부로 들어갈 수 있다. 이것이 포트 포워딩이라고 한다.
docker run -p <HOST>:<CONTAINER> <IMAGE>
vagrant@docker ~ docker run -d -p 8080:80 httpd
2cd2984cd63f2b44518c517b3e9b40ccab24e153b0359b5d50b6804278a741df
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2cd2984cd63f httpd "httpd-foreground" 3 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp romantic_hermann
vagrant@docker ~ docker run -d httpd
04f70d856ab6636bcd1192627b6d9ef53043fe83e717fbbab4b81efd06a49277
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04f70d856ab6 httpd "httpd-foreground" 3 seconds ago Up 2 seconds 80/tcp charming_cray
2cd2984cd63f httpd "httpd-foreground" 29 seconds ago Up 28 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp romantic_hermann
그냥 실행시켰을 때와 포트가 다르다.
밖에서 호스트의 8080 으로 접속하면 컨테이너의 80으로 전달시켜 준다.
vagrant@docker ~ sudo ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=69242,fd=4))
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=571,fd=13))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=675,fd=3))
LISTEN 0 4096 [::]:8080 [::]:* users:(("docker-proxy",pid=69247,fd=4))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=675,fd=4))
호스트의 8080으로 접속하면 docker-proxy 라는 것에 의해 컨테이너 내부의 80 포트로 연결된다.
vagrant@docker ~ docker run -d -p 8080:80 httpd
e72f33379de8ee929a93d894827843e57c9532791037bb1b60ff3e5a448094ff
docker: Error response from daemon: driver failed programming external connectivity on endpoint thirsty_pare (2324f5d35e9cb26b992e37bb38ddcf2f81200a33147825e37f9658088b36ec63): Bind for 0.0.0.0:8080 failed: port is already allocated.
포트가 이미 할당되어 있어 같은 포트를 사용할 수 없다.
이미 docker-proxy가 8080 포트를 잡아 사용하고 있는데 또 같은 명령을 내리면 docker-proxy가 또 다시 8080을 사용하려고 하므로 운영체제에서 거부한다.
같은 포트는 호스트에서 단 한번만 열 수 있다.
vagrant@docker ~ docker rm -f `docker ps -aq`
e72f33379de8
04f70d856ab6
2cd2984cd63f
vagrant@docker ~ sudo ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=571,fd=13))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=675,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=675,fd=4))
vagrant@docker ~ docker run -d -p 80:80 httpd
c953cec3a65f3790b6345edc1628b1bcc28544f6ec4a8764d5fc163df124e901
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c953cec3a65f httpd "httpd-foreground" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp lucid_bohr
'DevOps > Docker' 카테고리의 다른 글
[Docker] Docker Network - 1 (0) | 2022.05.10 |
---|---|
[Docker] Docker Volume (볼륨) (0) | 2022.05.09 |
[Docker] Docker 컨테이너 관리 명령어 (2) (0) | 2022.05.07 |
[Docker] Docker 컨테이너 관리 명령어 (1) (0) | 2022.05.07 |
[Docker] Docker 이미지 관리 명령어 (0) | 2022.05.07 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!