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-stagethis 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 /appthis is the working directory we want our Code to be executed at/app.COPY go.mod go.sum ./this code will copyinggo.modandgo.sumfile from local machine to./directory on Docker.RUN go mod downloadthis will executed commandgo mod downloadon 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.gothis code will executed command to build Golang app on linux OS to folder/apion 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-stagescratch 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 /apithis will copying directory/apifrom imagebuild-stageto/apionbuild-realease-stageimage.EXPOSE 8080this will expose port8080so we can access API with port8080outside 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.6this is the Image that we will use, similar toFROMat 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.0this service using Image mysql version 8.0 -
networks:this service using custom network namednewthen thenewnetwork 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 use3308as local-machine port because port3306already 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/migratethis service use migrate Image -
networks:this service using networknewsame asdbservice -
volumes:the migrations data from local./cmd/migrate/migrationsgot 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, thismigrateservice linked todbservice -
depends_on:this to make this service executed after certain condition,db: condition: service_healthythis meanmigrate-upservice will executed whendbservice 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 networknewso it can connect to servicedb, also connect to networkdefaultused 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 todbservice because its need to consume mysql database. -
depends_on:this service will executed on several condition, whenmigrate-up:alreadyservice_completed_successfully, whendbtest result isservice_healthy, and whennginxservice_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)