Table of Content
Overview
This Article wouldn't explain how Docker works on the hood, instead this Article will explain what the purpose on each code that written on Dockerfile
and docker-compose.yml
file so we can write our Docker configuration for other project.
Prerequisite
We need some project with Dockerfile and docker-compose for example, here we would use Golang Project named Ecom as example. For using Dockerfile you need to setup Local Database as mentioned on README.
Dockerfile
Dockerfile used to create a container image.(6)
# Build application from source
FROM golang:1.23.0 AS build-stage
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /api ./cmd/main.go
FROM golang:1.23.0 AS build-stage
this is an Image for our App, it's similar like we download Go engine to our Machine, Docker need specific Image to run our Code.(1)(2)WORKDIR /app
this is the working directory we want our Code to be executed at/app
.COPY go.mod go.sum ./
this code will copyinggo.mod
andgo.sum
file from local machine to./
directory on Docker.RUN go mod download
this will executed commandgo mod download
on DockerCOPY . .
this code will copy all file and folder project from local machine to Docker.RUN CGO_ENABLED=0 GOOS=linux go build -o /api ./cmd/main.go
this code will executed command to build Golang app on linux OS to folder/api
on Docker.
# Deploy application binary into a lean image
FROM scratch AS build-realease-stage
WORKDIR /
COPY --from=build-stage /api /api
EXPOSE 8080
ENTRYPOINT [ "/api" ]
FROM scratch AS build-realease-stage
scratch used to create minimal images containing only just what an application needs.WORKDIR /
we will using root/
as working directory.COPY --from=build-stage /api /api
this will copying directory/api
from imagebuild-stage
to/api
onbuild-realease-stage
image.EXPOSE 8080
this will expose port8080
so we can access API with port8080
outside Docker.ENTRYPOINT [ "/api" ]
this will set default executable at/api
Let's try our Dockerfile.
sudo docker build .
docker build
to build our project into an Image. You can add tags -t project-ecom
to easier identify Images you build.(3)
You can check the Image list with command sudo docker image ls
sudo docker run --rm --network host --env-file .env 98bc0128576e
Then Run our Docker Image
--rm
to remove container when stopped
--network host
to connect docker app to localhost machine (4),(5)
--env-file .env
to access environment value through .env file
98bc0128576e
docker image ID
Congratulation
You now can testing to Consume API with Postman or other apps.
Docker Compose
Docker Compose used to make multiple container services and run it inside Docker. In this project docker-compose.yml
there are 4 services that we will explain.
Services
A service is an abstract definition of a computing resource within an application which can be scaled or replaced independently from other components.(12)
Nginx Proxy
nginx:
image: nginxproxy/nginx-proxy:1.6
networks:
- default
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
HTTPS_METHOD: nohttps
-
nginx:
this is the service name -
image: nginxproxy/nginx-proxy:1.6
this is the Image that we will use, similar toFROM
at Dockerfile. -
networks:
this is the network inside Docker the service will use. -
ports:
this is to set port for service to use<local-machine-port>
:<docker-nginx-port>
, 80 is default port for HTTP -
volumes:
this is persistent Volume to store data for this service,<local-data-directory>
:<docker-directory>
:ro (read-only). -
environment:
this is to use environment variable.(8)
Mysql
db:
image: mysql:8.0
networks:
new:
aliases:
- database
healthcheck:
test: mysqladmin ping -h database -u ${DB_USER} --password=${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3308:3306"
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
-
db:
this is the service name -
image: mysql:8.0
this service using Image mysql version 8.0 -
networks:
this service using custom network namednew
then thenew
network using alias-namedatabase
-
healthcheck:
this is to check the service operation by running a test,test: mysqladmin ping -h database -u ${DB_USER} --password=${DB_PASSWORD}
this testing ping a mysql database. -
volumes:
this is to store persistent data inside volume. -
ports:
this is port the service will use, in this service we use3308
as local-machine port because port3306
already used for mysql on our local-machine. -
environment:
this is to using environment variable, in this mysql service we need root password and database name.(7)
Migrate
migrate-up:
image: migrate/migrate
networks:
- new
volumes:
- ./cmd/migrate/migrations:/migrations
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
command: ["-path", "/migrations", "-database", "${CONNECT_DB}", "-verbose", "up"]
links:
- db
depends_on:
db:
condition: service_healthy
-
migrate-up:
this is the service name -
image: migrate/migrate
this service use migrate Image -
networks:
this service using networknew
same asdb
service -
volumes:
the migrations data from local./cmd/migrate/migrations
got copied to service directory/migrations
-
command:
this is to run a command on this service,["-path", "/migrations", "-database", "${CONNECT_DB}", "-verbose", "up"]
this command similar tomigrate -path /migrations -database mysql://root:some-secret-password@tcp(database:3306)/ecom -verbose up
. (9) -
links:
this to link service to another service, thismigrate
service linked todb
service -
depends_on:
this to make this service executed after certain condition,db: condition: service_healthy
this meanmigrate-up
service will executed whendb
service test got resultservice_healthy
.
API
api:
networks:
- new
- default
build:
context: .
dockerfile: Dockerfile
restart: on-failure
volumes:
- .:/go/src/api
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "8080:8080"
environment:
VIRTUAL_HOST: ${PUBLIC_HOST}
DB_HOST: db
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_NAME: ${DB_NAME}
links:
- db
depends_on:
migrate-up:
condition: service_completed_successfully
db:
condition: service_healthy
nginx:
condition: service_started
-
api:
this is the service name -
networks:
this is network for this service, this service using networknew
so it can connect to servicedb
, also connect to networkdefault
used by servicenginx
. -
build:
this is to build the service, thi service usingDockerfile
. -
restart:
this service will restart whenever the serviceon-failure
-
volumes:
this is persistent data that stored on volume/go/src/api
. -
ports:
port for this service. -
environment:
environment value this service needed. -
links:
this service linked todb
service because its need to consume mysql database. -
depends_on:
this service will executed on several condition, whenmigrate-up:
alreadyservice_completed_successfully
, whendb
test result isservice_healthy
, and whennginx
service_started
Volumes
Volumes are persistent data stores implemented by the container engine.(10)
volumes:
db_data:
-
volumes:
this created persistent volume nameddb_data:
Networks
Networks let services communicate with each other.(11)
networks:
new:
-
networks:
this created networks namednew
Let's try our Docker Compose
sudo docker compose up -d
This command will create images for each services and run each container.
sudo docker compose ps --all
You can check the container our docker-compose.yml
created.
sudo docker volume ls
You can check volume our docker-compose.yml
created.
sudo docker image ls
You can check images our docker-compose.yml
created.
Congratulation
You can test Consume API from our project based on documentation on README with Postman or other apps.
if you have done you can stop the container with,
sudo docker compose stop
Or if you want to delete all container service inside docker compose you can run,
sudo docker compose down
References
(1)Dockerfile Reference
(2)Docker Base Image
(3)Docker Build
(4)Docker Network Tutorials
(5)Docker Network Drivers
(6)Writing a Dockerfile
(7)Docker Hub Mysql
(8)Nginx-Proxy Docs
(9)Golang Migrate
(10)Compose-file Volumes
(11)Compose-file Networks
(12)Compose-file Services
Top comments (0)