Originally posted on Ashraful's Blog
Do you like to spend more time to setup your environment? If yes? just close the window. Maybe you are not in the right place. Okay no more gossiping. Let me tell you a real story.
Recently I have bought a MacBook for my personal development. I was exited to write code on it. But before that I must setup my development environment to start with it. So, without delaying I started cloning repositories from Github and then installing their dev dependencies. Seriously at the end of the day I was damn tired of doing this. One of my pet project was using Node(v8.10.*), MongoDB and React. Another projects have latest version of Node and other dependencies. So I was on trouble setting up my environment as I was new at Mac OS. So, finally I had decided to write
Dockerfile at all my services and
Docker Compose to run them together.
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. More details here.
Suppose, we have two different services and one database service.
- NodeJS app (port: 5000)
- React app (port: 5001)
- MongoDB (port: 27017)
We are going to write
docker-compose.yml file and run them with single command anytime and anywhere. As I am not going to explain the code part rather than
docker-compose, So, I already have an app with this architecture. Fork and clone the app from github and change on your own.
As you already have seen we are going to run all these services/applications in different ports, So, we need to allow these ports in the container and physical machine(your machine). For example, If you already mongo installed on your computer then you may not use
27017 port for new mongo container. So, what we can do, we can forward the port from the docker container to the physical machine. It's simple as you think.
- Clone the repo,
git clone https://github.com/iashraful/graphql-mongo-todo.git
docker-compose.ymlwith your favorite editor. (Don;t worry I'll explain. 😎). You'll see similar like following.
version: '3.5' services: react_client: build: ./client command: sh -c "yarn install && yarn start" environment: - NODE_ENV=development - PORT=5001 ports: - '5001:5001' working_dir: /app/client volumes: - ./client:/app/client:cached node_server: build: ./server command: sh -c "yarn install && yarn dev" environment: - NODE_ENV=development - PORT=5000 ports: - '5000:5000' working_dir: /app/server volumes: - ./server:/app/server:cached depends_on: - mongodb mongodb: image: mongo expose: - '27017' environment: - MONGO_INIT_DB_DATABASE_NAME='graphql-todo' volumes: - ./db:/data/db ports: - '27019:27017'
This version indicates that, which docker engine version you are using. In my case I am using most recent docker engine 19.*.*. So, I am using version 3.7. See full versioning guide
It's plain and simple. How many services you want to run using this compose file. Mine is three. Node, React, Mongo.
Name of each service. Under each service you need to specify the configuration.
Which directory you are going to use for the particular services. You can specify the relative path here.
Command is fully depends on the image that you have chosen. If you pick an image that is based on linux then you know the bash is default shell. So, without any worrying you can use bash command. If you are confused about the image that I've chosen here? Don't worry I'll talk about it.
Any kind of environment variable you can pass through the
This is important to know how to enable port for container and map the physical machine port. Here
Container port:Physical machine port.
It's a straightforward path of the container where your code will be copied.
Volumes is most important to know when you are on local development. Because you don't like to re-build and run the container after every change. So, It creates a mapping between physical machine code vs container working directory codes.
It's an awesome feature we have. Suppose you have five services and one service depends on other. Like our nodejs service depends on mongodb. So, I put
Image is the docker image that we are using as a base image. As we already know from our previous post that, Every docker must have a base image.. This is the image tag we can use for defining the image. If you look closely, I didn't define image at
node_server. But on mongo I defined
image: mongo. Do you know why?? Let's see why.
Yes we can. Open client and server directory, you'll see Dockerfile is there. Even when you command your computer to runt the docker compose file then, your computer find the build directory and find a dockerfile inside it. Then execute as it is.
- Open up your terminal/console.
$ docker-compose up
- Wait few moments and enjoy.
docker-compose up➡️ Run the docker compose file.
docker-compose up --build➡️ Re build and run the docker compose file.
docker-compose up <service name>➡️ Up and running a specific services.
docker-compose start➡️ Start the last built containers.
docker-compose stop➡️ Stop the last running containers.
docker-compose restart➡️ Restart the last running containers.
docker-compose logs -f <service name>➡️ Log from a specific service.
docker-compose exec <service name> bash➡️ SSH into a particular container bash.
🚩 That's all. Thanks for reading! 😆