63

I have a docker-compose file running a few Dockerfiles to create my containers. I don't want to edit my Dockerfiles to set timezones because they could change at any time by members of my team and I have a docker-compose.override.yml file to make local environment changes. However, one of my containers (a Selenium based one) seems to not pull host time zone and that causes problems for me. Based on that I want to enforce timezones on all my containers. In my Dockerfiles right now I do

ENV TZ=America/Denver
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

And everything works fine. How do I replicate the same command in docker-compose syntax?

Yuri
  • 4,254
  • 1
  • 29
  • 46
nobody
  • 7,803
  • 11
  • 56
  • 91

6 Answers6

69

This is simple solution:

environment:
  - TZ=America/Denver
MxWild
  • 3,080
  • 2
  • 14
  • 15
52
version "2"

services:
  serviceA:
    ...
    environment:
      TZ: "America/Denver"
    command: >
      sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && 
      echo $TZ > /etc/timezone &&
      exec my-main-application"

Edit: The question didn't ask for it but I've just added exec my-main-application to show how the main process would be specified. exec is important here to make sure that my-main-application receives Ctrl-C (SIGINT/SIGKILL).

Bernard
  • 16,149
  • 12
  • 63
  • 66
  • 1
    Keep in mind that docker-compose's "command" overrides the default command, if any. Reference: https://docs.docker.com/compose/compose-file/#/command – Claudio d'Angelis Dec 22 '16 at 09:23
  • 1
    @Claudiod'Angelis That's correct, and that's also the desired behaviour here. On quick review of my code I realised that I need to specify how the main process for the container is started. Adding it now. – Bernard Dec 23 '16 at 00:22
  • what do I put for `my-main-application`? where does it take this name from? service name? name of dll? – lenny Jan 07 '19 at 16:45
  • @lennyy It's the name of your main executable inside your container. Add the path if it can't find it. – Bernard Jan 08 '19 at 01:15
  • @Alkaline So my `dockerfile` that was generated by VS for the docker project contains `ENTRYPOINT ["dotnet", "vote-server.dll"]`. would my `docker-compose` command therefore be `command: > sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && exec dotnet vote-server.dll"`? also, whenever I have a command in my docker-compose it won't start with the message that it can't find the server's container... I suppose it's because the command doesn't start the actual program, the container crashes and when it tries to work with it, its gone – lenny Jan 08 '19 at 08:24
  • If you have an ENTRYPOINT defined, then the `command` is passed as argument to the ENTRYPOINT executable. Not what you want here. To make it simpler here, just redefine `entrypoint: []` and only use `command:` as you wrote it above. See https://medium.freecodecamp.org/docker-entrypoint-cmd-dockerfile-best-practices-abc591c30e21 for the explanation. – Bernard Jan 17 '19 at 09:09
30

The easiest solution would be share volume in docker-compose.yml like this

ipchanger:
  image: codertarasvaskiv/ipchanger:raspberry
  volumes:
    - "/etc/localtime:/etc/localtime:ro"
  • ro - means container can only read from /etc/localtime of host-machine.
Taras Vaskiv
  • 2,215
  • 1
  • 18
  • 17
15
version: '3.6'
services:
  mysql:
    image: mysql:5.6
    restart: always
    container_name: dev-mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    restart: always
    environment:
     - TZ=Asia/Shanghai
     - MYSQL_ROOT_PASSWORD=password # set the root password
    ports:
      - '3306:3306'
    volumes:
      - "/etc/localtime:/etc/localtime:ro"
      - "/etc/timezone:/etc/timezone:ro"

This my docker-compose.yaml of mysql

Reminder,you need recreate container,other than restart. if you change the yaml need to recreate

docker-compose -f docker-compose.yaml stop
docker-compose -f docker-compose.yaml rm
docker-compose -f docker-compose.yaml start
ty4z2008
  • 350
  • 3
  • 8
1

Got the same problem on my Docker engine using Linux containers.

Resolved it by adding a script for installing tzdata package and setting the time zone to final stage of DockerFile for all targeted services using dated processes. The time zone is shared between all images like below:

.env file

COMMON_TIME_ZONE=Europe/Paris

docker-compose.yml

services:
  matfront:
    build: 
      context: ./my-app
      args:
         - TIME_ZONE=$COMMON_TIME_ZONE

Dockerfile

FROM tomcat:9.0
ARG TIME_ZONE
RUN rm -rf /usr/local/tomcat/webapps/*
COPY --from=maven /tmp/ApiDemo/target/ApiDemo.war /usr/local/tomcat/webapps

### Here is the script block that defines the desired timezone ###
# Get the package tzdata that is not installed by default, then set the defined TZ
RUN apt-get install tzdata
RUN ln -snf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime && echo ${TIME_ZONE} > /etc/timezone

EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
Shessuky
  • 1,846
  • 21
  • 24
0
 version: '2'
 services:
   ServiceA:
     image: image:
   - '/etc/localtime:/etc/localtime:ro'
Mugeesh Husain
  • 394
  • 4
  • 13