MOTOSHARE 🚗🏍️
Turning Idle Vehicles into Shared Rides & Earnings
From Idle to Income. From Parked to Purpose.
Earn by Sharing, Ride by Renting.
Where Owners Earn, Riders Move.
Owners Earn. Riders Move. Motoshare Connects.
With Motoshare, every parked vehicle finds a purpose.
Owners earn. Renters ride.
🚀 Everyone wins.
The services
keyword in GitLab CI/CD allows you to run additional Docker containers alongside the main Docker container for your job. These service containers typically provide dependencies that your job needs during its execution, such as a database (like PostgreSQL, MySQL), a caching service (like Redis), or any other network-accessible service.
The main job container can then connect to these service containers over the network.
Example .gitlab-ci.yml
with services
:
This example will use a PostgreSQL database as a service for a job that needs to interact with it.
YAML
# .gitlab-ci.yml
stages:
- test
# Job that needs a PostgreSQL database
integration_test_with_db:
stage: test
image: alpine:latest # A lightweight image for the main job
variables:
# These variables are used by the job to connect to the PostgreSQL service.
# They match the ones used by the PostgreSQL service itself.
DB_USER: "testuser"
DB_PASSWORD: "testpassword"
DB_NAME: "testdb"
DB_HOST: "postgres" # Default hostname for the service (derived from image name)
services:
- name: postgres:14-alpine # Specifies the Docker image for the PostgreSQL service
alias: db-server # Optional: A custom hostname alias for this service
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] # Optional: Custom command for the service
variables:
# Environment variables for the PostgreSQL service container itself
POSTGRES_USER: $DB_USER # Use the job-level variable
POSTGRES_PASSWORD: $DB_PASSWORD
POSTGRES_DB: $DB_NAME
# For faster startup in CI, not recommended for production PG
POSTGRES_HOST_AUTH_METHOD: "trust"
before_script:
- echo "Installing PostgreSQL client in the main job container..."
- apk update
- apk add --no-cache postgresql14-client # Install psql client for version 14
script:
- echo "--- Running Integration Tests ---"
- echo "Waiting for PostgreSQL service to be ready..."
# GitLab CI generally waits for services to be ready, but a small sleep or retry loop might be needed in complex cases.
# For PostgreSQL, the service itself takes a moment to initialize the database.
- sleep 15 # Give PostgreSQL a bit more time to initialize fully
- echo "Attempting to connect to PostgreSQL service at host: $DB_HOST (or alias 'db-server')"
# Test connection using the default service name 'postgres' as hostname
- PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "SELECT version();"
- PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "CREATE TABLE IF NOT EXISTS my_table (id SERIAL PRIMARY KEY, data VARCHAR(100));"
- PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "INSERT INTO my_table (data) VALUES ('Hello from GitLab CI via default service name!');"
# Test connection using the alias 'db-server'
- PGPASSWORD=$DB_PASSWORD psql -h db-server -U $DB_USER -d $DB_NAME -c "INSERT INTO my_table (data) VALUES ('Hello from GitLab CI via alias!');"
- PGPASSWORD=$DB_PASSWORD psql -h db-server -U $DB_USER -d $DB_NAME -c "SELECT * FROM my_table;"
- echo "Integration tests requiring database would run here."
Code language: PHP (php)
Explanation:
services:
Keyword:- This keyword is defined at the job level (e.g., within
integration_test_with_db
). - It takes a list of service definitions. Each service runs in its own Docker container, linked to the main job’s container.
- This keyword is defined at the job level (e.g., within
- Service Definition:
name: postgres:14-alpine
:- This is the most crucial part. It specifies the Docker image to be used for the service. Here,
postgres:14-alpine
will pull the official PostgreSQL version 14 image (Alpine variant, which is smaller). - By default, the hostname your job will use to connect to this service will be derived from the image name (e.g.,
postgres
).
- This is the most crucial part. It specifies the Docker image to be used for the service. Here,
alias: db-server
:- (Optional) This provides an additional hostname (an alias) that your job can use to connect to this service. So, your job can reach this PostgreSQL instance via
postgres
(default) ordb-server
(alias). This is useful if you want a more generic name or if the image name contains characters not suitable for a hostname.
- (Optional) This provides an additional hostname (an alias) that your job can use to connect to this service. So, your job can reach this PostgreSQL instance via
command: ["postgres", "-c", "fsync=off", ...]
:- (Optional) You can override the default command or entrypoint of the service’s Docker image. Here, we’re passing some flags to PostgreSQL to potentially speed up its startup in a CI environment by disabling durability features not critical for CI tests. These specific flags are for CI optimization and should not be used in production.
variables:
(under the service definition):- These are environment variables passed specifically to the service container (
postgres:14-alpine
in this case) when it starts. POSTGRES_USER: $DB_USER
,POSTGRES_PASSWORD: $DB_PASSWORD
,POSTGRES_DB: $DB_NAME
: These are standard environment variables that thepostgres
Docker image uses to initialize the database with a specific user, password, and database name. We are conveniently using the job-level variables (defined underintegration_test_with_db.variables
) to set these.POSTGRES_HOST_AUTH_METHOD: "trust"
: This tells PostgreSQL to allow connections without password authentication from any host it can reach (which includes the job container on the same Docker network). This simplifies connections in CI but is highly insecure for production.
- These are environment variables passed specifically to the service container (
- Job-Level
variables:
(withinintegration_test_with_db
):DB_USER
,DB_PASSWORD
,DB_NAME
,DB_HOST
: These are defined for the main job container. The job’s script uses these to know how to connect to the database service.DB_HOST
is set topostgres
, which is the default hostname for the service based on its image name.
before_script:
(withinintegration_test_with_db
):- The main job image is
alpine:latest
, which doesn’t have thepsql
(PostgreSQL client) command-line tool. apk update && apk add --no-cache postgresql14-client
: This installs thepsql
client inside the job’s container so it can interact with the PostgreSQL service.
- The main job image is
script:
(withinintegration_test_with_db
):sleep 15
: GitLab CI attempts to ensure services are ready before the job script starts, but complex services like databases might need a few extra seconds to initialize fully after the container is up and networking is established. This explicit sleep can help prevent connection issues. More robust solutions involve retry loops for connections.PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST ...
: This is how thepsql
client connects to the PostgreSQL service.-h $DB_HOST
: Specifies the hostname of the database server. This will resolve to the IP address of thepostgres
service container. We could also use-h db-server
because of the alias.-U $DB_USER
: Specifies the database user.-d $DB_NAME
: Specifies the database name.PGPASSWORD=$DB_PASSWORD
: Sets the password via an environment variable forpsql
to avoid interactive prompts.
How It Works and Key Concepts:
- Network Linking: GitLab creates a Docker network for the job. The main job container and all its service containers are attached to this same network. This allows them to communicate with each other using their container names (or aliases) as hostnames.
- Service Lifecycle: Service containers are started before the
before_script
of your job runs and are stopped after theafter_script
of your job completes. - Hostname Resolution:
- By default, a service is reachable via a hostname derived from its image name (e.g.,
postgres:14-alpine
becomespostgres
). - If an
alias
is provided, that alias can also be used as a hostname.
- By default, a service is reachable via a hostname derived from its image name (e.g.,
- Common Use Cases:
- Databases:
postgres
,mysql
,mariadb
,mongo
for integration testing. - Caching:
redis
,memcached
. - Message Queues:
rabbitmq
,kafka
(though Kafka might be more complex for a simple service). - Web Servers/APIs: Running a backend API service that your frontend tests need to interact with.
- Selenium/Browser Testing: Services like
selenium/standalone-chrome
.
- Databases:
Using services
is essential for running integration tests or any job that relies on external network-accessible dependencies, allowing you to create a more realistic and self-contained testing environment within your CI pipeline.